{"record":{"id":"27bcc6ea42537c29","repo":"stablyai/orca","slug":"codex-reset-attempt-idempotency-key-is-invalid","errorCode":null,"errorMessage":"Codex reset attempt idempotency key is invalid","messagePattern":"Codex reset attempt idempotency key is invalid","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mobile/src/storage/codex-reset-attempt-journal.ts","lineNumber":147,"sourceCode":"    if (scopeMutations.get(key) === tail) {\n      scopeMutations.delete(key)\n    }\n  }\n}\n\nexport async function getOrCreateCodexResetAttempt(\n  identity: AttemptIdentity & { createIdempotencyKey: () => string }\n): Promise<CodexResetAttempt> {\n  return withScopeMutation(identity, async () => {\n    const key = storageKey(identity)\n    const raw = await AsyncStorage.getItem(key)\n    if (raw !== null) {\n      return parseAttempt(raw, identity)\n    }\n\n    const idempotencyKey = identity.createIdempotencyKey()\n    if (!IdempotencyKeySchema.safeParse(idempotencyKey).success) {\n      throw new Error('Codex reset attempt idempotency key is invalid')\n    }\n    const attempt = CodexResetAttemptSchema.parse({\n      v: 1,\n      hostId: identity.hostId,\n      expectedScope: identity.expectedScope,\n      idempotencyKey\n    })\n    // Why: the key must survive a committed provider mutation whose response is\n    // lost; no reset RPC may start until this write has completed successfully.\n    await AsyncStorage.setItem(key, JSON.stringify(attempt))\n    return attempt\n  })\n}\n\nexport async function clearCodexResetAttemptAfterAuthoritativeResponse(\n  identity: AttemptIdentity & { idempotencyKey: string }\n): Promise<void> {\n  return withScopeMutation(identity, async () => {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/mobile/src/storage/codex-reset-attempt-journal.ts#L129-L165","documentation":"Thrown by `getOrCreateCodexResetAttempt` when a new attempt must be created (no existing entry) and the caller-supplied `createIdempotencyKey()` returns a value that fails `IdempotencyKeySchema` — which is `z.uuid()`. The idempotency key is what makes the downstream reset RPC safely retryable after a lost response, so it must be a well-formed UUID before it is ever persisted.","triggerScenarios":"First-time reset for an account scope where AsyncStorage has no entry, and the `createIdempotencyKey` callback returns a non-UUID string (wrong format, empty, contains invalid characters, or not lowercase canonical form).","commonSituations":"The key generator uses a non-UUID source (timestamp, random hex of wrong length); a UUID library returns an uppercased or braced form that `z.uuid()` rejects; the callback was stubbed incorrectly in tests; v4 vs v1 UUID format mismatch.","solutions":["Make `createIdempotencyKey` return a canonical lowercase v4 UUID (e.g. via `crypto.randomUUID()` or `uuid.v4()`).","Add a unit test asserting the generator output passes `z.uuid()`.","Strip braces and lowercase the value before returning if using a legacy UUID formatter.","If using a custom generator, validate it against the UUID regex `^[0-9a-f]{8}-...$` upstream."],"exampleFix":"// before — non-UUID key\ncreateIdempotencyKey: () => `${Date.now()}`\n\n// after — canonical UUID\ncreateIdempotencyKey: () => crypto.randomUUID()","handlingStrategy":"validation","validationCode":"// Validate the key shape before it reaches the journal.\nimport { z } from 'zod'\nconst IdempotencyKeySchema = z.uuid()\nconst key = identity.createIdempotencyKey()\nif (!IdempotencyKeySchema.safeParse(key).success) {\n  throw new Error('createIdempotencyKey must return a canonical UUID')\n}","typeGuard":"function isUuid(value: string): boolean {\n  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)\n}","tryCatchPattern":null,"preventionTips":["Implement createIdempotencyKey with crypto.randomUUID() or uuid.v4().","Unit-test the generator against z.uuid().","Never substitute timestamps or short random strings for the idempotency key."],"tags":["storage","validation","uuid","idempotency","zod"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}