{"record":{"id":"a5d22fba1d62bffe","repo":"ruvnet/ruflo","slug":"message-content-is-not-canonical-json","errorCode":null,"errorMessage":"message content is not canonical JSON","messagePattern":"message content is not canonical JSON","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/codex/src/harness/in-memory-inbox-reference.ts","lineNumber":75,"sourceCode":"    record: InMemoryInboxRecord;\n  }>();\n  private readonly quarantined: InMemoryQuarantinedMessage[] = [];\n  private nextCursor = 1n;\n\n  constructor(private readonly now: () => number = Date.now) {}\n\n  send(message: HarnessMessage): MessageReceipt {\n    if (!message.messageId.trim() || !message.issuer.trim() || !message.audience.trim()) {\n      throw new Error('message ID, issuer, and audience are required');\n    }\n    const identity = inMemoryInboxIdentityKey(message.issuer, message.messageId);\n    const receivedAt = new Date(this.now()).toISOString();\n    let suppliedDigest: string;\n    try {\n      suppliedDigest = harnessMessageContentDigest(message.content);\n    } catch {\n      this.quarantine(message, 'content-digest-mismatch', receivedAt);\n      throw new Error('message content is not canonical JSON');\n    }\n    if (suppliedDigest !== message.contentDigest) {\n      this.quarantine(message, 'content-digest-mismatch', receivedAt);\n      throw new Error('message contentDigest does not match canonical content');\n    }\n    try {\n      parseCanonicalUnsigned(message.sequence, 'message sequence');\n    } catch {\n      throw new Error('message sequence must be a canonical unsigned decimal integer');\n    }\n    if (message.expiresAt !== undefined && !Number.isFinite(Date.parse(message.expiresAt))) {\n      throw new Error('message expiresAt must be an ISO timestamp');\n    }\n\n    const envelopeDigest = sha256(canonicalJson(message));\n    const prior = this.byIdentity.get(identity);\n    if (prior) {\n      if (prior.issuer !== message.issuer || prior.messageId !== message.messageId) {","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/codex/src/harness/in-memory-inbox-reference.ts#L57-L93","documentation":"Thrown when message content fails canonical JSON validation. Defense: serialize content with the canonical JSON serializer (sorted keys, no undefined, no lone surrogates) before computing digests or posting.","triggerScenarios":"Thrown at v3/@claude-flow/codex/src/harness/in-memory-inbox-reference.ts:75 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Serialize message content with the canonical JSON serializer (sorted keys, no undefined, NFC strings) instead of JSON.stringify on arbitrary input.","Strip unsupported values (undefined, functions, symbols, cycles) from the content before posting."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}