{"record":{"id":"28a5390ddd6c92da","repo":"thedotmack/claude-mem","slug":"canonical-content-message","errorCode":null,"errorMessage":"canonical content: ${message}","messagePattern":"canonical content: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":409,"severity":"error","filePath":"workers/sync-hub/src/canonical-content.ts","lineNumber":59,"sourceCode":"const ENVELOPE_KEYS = [\n\t\"body_schema_version\",\n\t\"deleted\",\n\t\"deleted_at\",\n\t\"entity_rev\",\n\t\"id\",\n\t\"kind\",\n\t\"mutation\",\n\t\"origin_device_id\",\n\t\"origin_local_id\",\n\t\"payload\",\n\t\"payload_schema_version\",\n\t\"payload_sha256\",\n] as const;\n\nconst encoder = new TextEncoder();\n\nfunction invalid(message: string): never {\n\tthrow new Error(`canonical content: ${message}`);\n}\n\n/** RFC-8259 JSON with recursively sorted object keys and preserved array order. */\nexport function canonicalJson(value: unknown): string {\n\treturn JSON.stringify(normalizeJson(value, new Set()));\n}\n\nfunction normalizeJson(value: unknown, seen: Set<object>): unknown {\n\tif (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value;\n\tif (typeof value === \"number\") {\n\t\tif (!Number.isFinite(value)) invalid(\"numbers must be finite\");\n\t\tif (!Number.isSafeInteger(value) && Number.isInteger(value)) {\n\t\t\tinvalid(\"integers must be safe; use decimal strings for uint64 values\");\n\t\t}\n\t\tif (Object.is(value, -0)) return 0;\n\t\treturn value;\n\t}\n\tif (typeof value !== \"object\") invalid(`unsupported JSON value ${typeof value}`);","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/workers/sync-hub/src/canonical-content.ts#L41-L77","documentation":"Error \"canonical content: ${message}\" thrown in thedotmack/claude-mem.","triggerScenarios":"Fires in the sync hub when canonicalizing entity content fails: non-object payloads, missing required fields, or values that cannot be serialized into canonical form. Guard at workers/sync-hub/src/canonical-content.ts:59 rejects malformed operations before they are sequenced, so bad content never enters the canonical log.","commonSituations":"See trigger scenarios.","solutions":["Fix the operation payload so it satisfies canonical-content rules (required fields present, correct types, valid sha256); the message names the specific violation.","If the validator is wrong, update canonical-content.ts and its tests together."],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}