affaan-m/ECC · error · ClaimError

completion requires the correct dispatch/reconciliation…

Error message

completion requires the correct dispatch/reconciliation state

What it means

_finish raises this when the claim's state is neither the expected completion state nor 'delivered'. For complete() (evidence=None) the claim must be 'dispatching'; for reconcile() the claim must be 'unknown'. This guarantees completion is only recorded for an attempt that was actually dispatched, or one whose uncertainty has been reconciled with evidence.

Solutions

  1. For a normal delivery: call begin_dispatch first, send, then complete().
  2. After an uncertain dispatch: call mark_unknown() first, then reconcile() with trusted evidence.
  3. Select the finisher from the current state: state 'dispatching' -> complete(); state 'unknown' -> reconcile(); anything else -> not completable.
  4. Check state before calling: SELECT state FROM obligation_delivery_claims WHERE token=?.

Example fix

// before: complete without ever dispatching
claims.complete(db, token, coordinate, now=ts)  # state 'claimed' -> ClaimError

// after
claims.begin_dispatch(db, token, now=ts)
send(payload)
claims.complete(db, token, coordinate, now=ts)
# uncertain path:
# claims.mark_unknown(...); claims.reconcile(db, token, coordinate, evidence, now=ts)
Defensive patterns

Strategy: validation

Validate before calling

state = db.execute("SELECT state FROM obligation_delivery_claims WHERE token=?", (token,)).fetchone()['state']
if state == 'dispatching':
    finisher = lambda: claims.complete(db, token, coordinate, now=ts)
elif state == 'unknown':
    finisher = lambda: claims.reconcile(db, token, coordinate, evidence, now=ts)
else:
    raise ValueError(f"claim not completable in state {state}")

Try / catch

try:
    finisher()
except claims.ClaimError as e:
    log.error("finish refused for %s: %s", token, e)

Prevention

When it happens

Trigger: Calling complete() on a claim still in 'claimed' (begin_dispatch never called) or in 'unknown'; calling reconcile() on a claim in 'claimed' or 'dispatching'; calling either on a 'cancelled' claim.

Common situations: Skipping begin_dispatch and calling complete directly on a fresh token; calling reconcile before mark_unknown after a failed dispatch; recovery code calling the wrong finisher for the current state.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/2934514bd0b6c8e8. Report an issue: GitHub.

Appendix: source

Thrown at skills/operator-approval-loop/references/approval_claims.py:143

        db.execute("UPDATE obligation_delivery_claims SET state='unknown',updated_ts=? WHERE token=?",
                   (now, token))


def _finish(db, token, coordinate, now, evidence):
    if not isinstance(coordinate, str) or not coordinate.strip():
        raise ClaimError('a confirmed nonempty coordinate is required')
    with _transaction(db, now):
        row = _claim_row(db, token)
        receipt = db.execute('''SELECT * FROM obligation_deliveries
            WHERE obligation_id=? AND decision_id=?''',
                             (row['obligation_id'], row['decision_id'])).fetchone()
        if row['state'] == 'delivered':
            if receipt is None or receipt['coordinate'] != coordinate or receipt['kind'] != 'draft_sent':
                raise ClaimError('completion contradicts the existing receipt')
            return False
        expected_state = 'dispatching' if evidence is None else 'unknown'
        if row['state'] != expected_state:
            raise ClaimError('completion requires the correct dispatch/reconciliation state')
        _snapshot(db, row['obligation_id'], row['decision_id'])
        db.execute('''INSERT INTO obligation_deliveries
            (obligation_id,decision_id,kind,coordinate,delivered_ts) VALUES (?,?,'draft_sent',?,?)''',
                   (row['obligation_id'], row['decision_id'], coordinate, now))
        db.execute('''UPDATE obligation_delivery_claims
            SET state='delivered',updated_ts=?,reconciliation_evidence=? WHERE token=?''',
                   (now, evidence, token))
        changed = db.execute("UPDATE obligations SET status='sent' WHERE id=? AND status='approved'",
                             (row['obligation_id'],)).rowcount
        if changed != 1:
            raise ClaimError('obligation completion failed')
    return True


def complete(db, token, coordinate, *, now):
    """Atomically record a confirmed result; identical duplicate completion is a no-op."""
    return _finish(db, token, coordinate, now, None)

View on GitHub (pinned to 8321021c54)