Skip to content

REQ-C-028: ALREADY_EXISTS Response Pattern

Tier: Command Contract | Priority: P1

Source: Silent assumption — agents retry failed creates; if create fails because the resource already exists, the agent needs the existing resource returned so it can proceed without a separate get call

Addresses: Severity: High / Token Spend: Medium / Time: Medium / Context: Low


Description

Commands that create resources MUST handle the "resource already exists" case by returning a structured ALREADY_EXISTS response — not a generic error. The response MUST include the existing resource in the data field (identical to what a get command would return), set "ok": false, use exit code from the command's declared exit code table (a dedicated code, not 1), and set "retryable": false.

This pattern allows agents that retry failed creates to recover gracefully: they receive the existing resource and can proceed as if the create succeeded. Without this pattern, agents must make a separate get call after every create failure to determine whether the failure was a conflict or a genuine error.

The inverse — delete on a non-existent resource — MUST exit 0 with {"ok": true, "data": {"status": "not_found"}}.

Acceptance Criteria

  • tool resource create --name foo called twice returns the resource on both calls
  • Second call: "ok": false, exit code ALREADY_EXISTS (declared in exit code table), data contains the existing resource
  • Agent can use data from the second call directly without a follow-up get
  • Delete of non-existent resource exits 0 with structured not_found confirmation
  • Both ALREADY_EXISTS and NOT_FOUND (on delete) are declared in the command's exit code table

Schema

exit-code-entry — commands must declare an ALREADY_EXISTS exit code entry; response-envelope carries the existing resource in data


Wire Format

Create called on existing resource:

{
  "ok": false,
  "data": {
    "id": "res_123",
    "name": "foo",
    "created_at": "2026-01-01T00:00:00Z",
    "status": "active"
  },
  "error": {
    "code": "ALREADY_EXISTS",
    "message": "Resource 'foo' already exists",
    "retryable": false,
    "conflict_id": "res_123"
  }
}

Delete called on non-existent resource:

{
  "ok": true,
  "data": {"status": "not_found", "id": "res_999"},
  "error": null
}

Example

Agent create-or-get pattern:

result = run("tool resource create --name foo")
if result.exit_code == 0:
    resource = result.data          # newly created
elif result.error.code == "ALREADY_EXISTS":
    resource = result.data          # existing — no extra get call needed
else:
    raise result.error              # genuine failure

Requirement Tier Relationship
REQ-C-007 C Composes: idempotency key prevents ALREADY_EXISTS on intentional retries
REQ-C-003 C Provides: effect field distinguishes create (non-idempotent) from apply (idempotent)
REQ-C-001 C Provides: ALREADY_EXISTS exit code must be declared in the command's exit code table
REQ-F-004 F Provides: response envelope that carries the existing resource in data on conflict