## TL;DR

The join key is too strict: it demands exact equality on fields that legitimately differ. Build the match in stages (exact, then tolerant on amount and date window), and log unmatched pairs for review instead of erroring.

## Error

```text
agent failed to match the card transaction to the receipt: key error
```

## Steps

1. Inspect the join key: which fields must match exactly. Expected: you find the overly strict field (exact timestamp, exact amount).
2. Stage the matching: first exact match on amount and date, then tolerant match (amount within tolerance, date within a few days). Expected: most pairs match in stage one or two.
3. Add the payment-method last digits to the key where available. Expected: a strong disambiguator for same-day same-amount charges.
4. Log every unmatched transaction and receipt with the attempted keys. Expected: a reviewable list instead of an error.
5. Review the unmatched list weekly to catch systematic key problems. Expected: the key improves over time.

## When to use

- An agent errors joining card transactions to receipts.
- The join key demands exact equality on noisy fields.

## When not to use

- Amounts differ beyond tolerance (see the amount-mismatch skill).
- Receipts are missing (see the missing-receipt skills).

## Tool compatibility

- Custom audit agents; card transaction feeds and receipt stores.

## Variant phrasings

### Could not join transaction to receipt

Same failure, database wording.

### Transaction-receipt match key failed

Names the key directly.

## Why it happens

Real-world fields are noisy: timestamps differ by timezone, amounts differ by tip, dates differ by posting delay. An exact-equality join treats normal noise as a missing key.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_i7pGpV50KgpQft7d56IBPQ
