Diagnosing FaunaDB Unique-Index Write Failures
Diagnose and fix FaunaDB unique-index write failures without weakening the constraint, including concurrent writes, normalization drift, and index-definition mismatches.
05 Jul 2025, 14:08 UTC

Problem and takeaway
A create or update is rejected with a unique-constraint error (the index refuses a duplicate value for the indexed field). The intended document is not committed, and repeating the same request with the same indexed value usually produces the same result. Before changing data, capture the exact error, collection, index, attempted value, and transaction context.
Useful takeaway: treat the unique index as the authority for business-key uniqueness. An application-side lookup or read-before-write check can help with diagnostics, but it does not replace the constraint because two concurrent transactions can both observe an apparently free key and then collide when they commit.
Recognizable condition
The failure appears as a rejected write with a uniqueness conflict. The document is absent after the request, and a direct lookup for the indexed value either finds an existing owner or finds nothing while the write still fails. The latter case points to concurrent commits, normalization drift, or an incorrect index definition rather than a simple duplicate row.
Cause and diagnostic table
| Condition | Typical behavior | Likely cause |
|---|---|---|
| Existing owner | Serial reproduction fails every time; direct inspection finds a document with the same indexed value | Duplicate business key already present |
| Concurrent writers | Serial execution succeeds; simultaneous transactions produce one success and one conflict | Two writers racing for the same key |
| Normalization mismatch | Values differ only by case, whitespace, or encoding | Write and index canonicalization disagree |
| Wrong index definition | Conflict maps to an unexpected collection or field, or the inspected index is not unique | Deployed index does not match the intended business rule |
| Duplicate migration rows | Backfill or index creation reports multiple existing owners | Duplicates were written before uniqueness was enforced |
Ordered checks
- Record the operation and exact error. Note the collection, index name, attempted indexed value, and whether the request runs inside a transaction. Do not rely on paraphrased error text; wording varies by FaunaDB version and client.
- Inspect the deployed index definition. Confirm its collection, source field or fields, uniqueness flag, and any term or value definitions. A unique index on a single field does not express a composite rule such as one record per tenant plus email.
- Inspect existing documents directly. Compare the stored key values with the attempted value after applying the same canonicalization (converting values to a standard form, such as lowercase and trimmed text) the index uses.
- Reproduce serially in a disposable collection. Create a test collection, deploy the same index definition, insert one document, and attempt a second insert with the same value. Confirm rejection and that the first document remains unchanged.
- Reproduce concurrently. Run two transactions that attempt the same unique key with different document identifiers. Confirm that exactly one succeeds and the other reports a uniqueness conflict.
- Review migrations and clients for inconsistent normalization. Check whether one path lowercases or trims values before writing while another does not, or whether the index normalizes differently than the application.
Fixes tied to findings
Existing owner
Update or remove the correct document rather than bypassing the constraint. If the obsolete record should keep history, mark it inactive or move it to an archive collection, but do not delete the unique index to clear the error.
Concurrent writers
Use a deterministic document identifier where possible. Make the operation idempotent (safe to repeat without changing the result after the first successful commit) and retry the complete transaction with bounded backoff (retry attempts spaced by increasing delays up to a maximum limit). Retry the entire transaction, not an isolated write step, and only when external side effects are also idempotent.
Normalization drift
Canonicalize at the write boundary before the document is created and before the indexed value is computed, then backfill existing values so the index and stored documents agree. Do not rely on application-side cleanup after the index is already enforcing uniqueness.
Definition mismatch
Correct the deployed index rather than adding an unrelated constraint. If the intended rule is one record per email, tenant plus email, or another composite key, verify that the indexed representation matches that rule exactly before re-deploying.
Duplicate migration rows
Resolve duplicates deterministically before enforcing uniqueness. Choose a canonical owner for each business key, update or archive the others, then create or re-deploy the unique index.
Concrete verification example
In a disposable collection, create a unique index on a test field, insert one document, and attempt a second insert with the same value. The expected result is rejection of the second insert while the first document remains unchanged. Then run two concurrent transactions that attempt the same unique key using different document identifiers; exactly one should succeed and the other should report a uniqueness conflict. Repeat these checks against the exact FaunaDB version and client used by the application, recording the observed error code and message rather than assuming wording from another environment.
Run schema inspection and test writes against a non-production database using a key with schema read and write permissions. Replace placeholders such as COLLECTION_NAME, INDEX_NAME, and KEY_VALUE with values from your environment. Do not run index creation or deletion against production without a maintenance window and a rollback plan.
# Illustrative only; syntax depends on FaunaDB version and driver.
# Verify against your target environment before use.
Inspect index: Index.byName(INDEX_NAME)
Test write: Create(COLLECTION_NAME, { data: { FIELD: KEY_VALUE } })
Risk: an incorrect index definition change can make existing writes fail or allow duplicates. Verify the definition in a staging copy of the production schema first.
Escalation criteria
Escalate when:
- A serial reproduction succeeds but the same environment still rejects the write.
- Deployed index metadata differs from the expected definition.
- Duplicate owners remain after canonicalization.
- A retry produces partial external side effects.
Provide a sanitized request, transaction identifier, timestamps, schema and index definitions, and the smallest reproducible sequence.
Limitations
Exact error text, index-definition syntax, and missing or null-value behavior can vary by FaunaDB version and client. A successful lookup showing no duplicate is not proof of uniqueness when another transaction can commit concurrently. Do not remove or weaken a unique index merely to clear an error; that can allow duplicate business records to persist. Uniqueness is scoped to the index and its collection; do not assume it spans collections.
How to check the result
After applying a fix, repeat the serial check: insert one document with the business key, then attempt a second insert with the same key. The second should be rejected and the first unchanged. Then repeat the concurrent check: two transactions, same key, different identifiers; exactly one should succeed. Confirm the deployed index definition still matches the intended collection, fields, and uniqueness setting.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.