From 476535c9a7c631c06b05d67af6bd91855641d5bf Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 5 Sep 2026 00:09:30 +0000 Subject: [PATCH] docs(protocol): the 409 unique-constraint refusal is UNIQUE_VIOLATION on the wire; DUPLICATE_RECORD is the engine's in-process code (#15362) Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk --- .../docs/protocol/kernel/error-handling.mdx | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/content/docs/protocol/kernel/error-handling.mdx b/content/docs/protocol/kernel/error-handling.mdx index 74ca26bbf2..d047175ce7 100644 --- a/content/docs/protocol/kernel/error-handling.mdx +++ b/content/docs/protocol/kernel/error-handling.mdx @@ -346,27 +346,27 @@ deriving it from this page. - Check user has permission to see resource (row-level security) - Resource may have been deleted -#### `DUPLICATE_RECORD` +#### `UNIQUE_VIOLATION` **HTTP Status:** 409 -**Meaning:** Resource with unique constraint already exists +**Meaning:** The write collides with a unique constraint — a record already holds that value **Example:** ```json { - "success": false, - "error": { - "code": "DUPLICATE_RECORD", - "message": "Account with email 'john@acme.com' already exists", - "details": { - "resource": "account", - "constraint": "unique", - "field": "email", - "value": "john@acme.com" - } - } + "error": "A record with this email already exists", + "code": "UNIQUE_VIOLATION", + "field": "email", + "object": "account" } ``` +The engine throws `DuplicateRecordError`, whose in-process `code` is +`DUPLICATE_RECORD`; the REST door translates that envelope at the boundary, so +every route answers the wire code `UNIQUE_VIOLATION` and the in-process spelling +never crosses HTTP. The refusal is emitted as the flat body shown above, and +`field` is best-effort — see +[HTTP API](/docs/protocol/kernel/http-protocol) for the degraded shape. + **How to fix:** - Check for existing resource before creating - Update existing resource instead of creating new one @@ -947,7 +947,7 @@ Even error responses can be abused: // Attacker tries to enumerate user emails for (let i = 0; i < 1000000; i++) { await register({ email: `user${i}@example.com` }); - // Response: "DUPLICATE_RECORD" or "VALIDATION_ERROR" + // Response: "UNIQUE_VIOLATION" or "VALIDATION_ERROR" } ```