OriginChain docs
examples · errors · 13 / 19

13. 409 - optimistic-concurrency conflict

← Errors examples
what this error means

Important context first: by default, OriginChain row writes are last-writer-wins - two concurrent PUTs on the same key both succeed, and the later one overwrites the earlier one. No 409.

OCC (optimistic concurrency control) is opt-in. You enable it by passing the row's current version in an If-Match: <oc_row_version> header. If the row's actual version differs at commit time, the write is rejected with this 409 and the body tells you the current version so you can re-fetch, re-apply, and retry.

what triggers it

A conditional PUT where the If-Match version no longer matches.

PUT /v1/tenants/:t/rows/:table/:pk with If-Match
curl -X PUT "https://$OC_HOST/v1/tenants/$OC_TENANT/rows/shop.customers/c_42" \
  -H "Authorization: Bearer $OC_TOKEN" \
  -H "If-Match: 17" \
  -H "Content-Type: application/json" \
  -d '{"id": "c_42", "email": "alice@example.com", "tier": "platinum"}'
the canonical response body
{
  "error": "write_conflict",
  "message": "row 'c_42' is at version 18, expected 17",
  "retry": true,
  "current_version": 18
}
how to recover
  • Re-read the row to get the current state and version.
  • Re-apply your business logic on top of the new state (merge, re-validate, etc).
  • Retry the PUT with If-Match: <new_version>.
  • The SDKs offer a update_with_retry() helper that wraps the read-merge-retry loop.
  • retry: true - but only after re-fetching. Blind retry of the same bytes will fail the same way.
common upstream causes
  • Two workers picking up the same job from a queue and racing on the same row.
  • Background reconciler and user-facing edit landing in the same millisecond.
  • Re-using a stale version number from an in-memory cache.
  • Mobile client with an offline edit syncing after the server already advanced.
  • Wrong row's version copied into If-Match from another response.