{"record":{"id":"7f18e7ddc82bc1cf","repo":"ruvnet/ruflo","slug":"canonical-json-does-not-support-typeof-item","errorCode":null,"errorMessage":"canonical JSON does not support ${typeof item}","messagePattern":"canonical JSON does not support (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/codex/src/harness/repository-state.ts","lineNumber":129,"sourceCode":"  const encode = (item: unknown): string => {\n    if (item === null || typeof item === 'boolean') return JSON.stringify(item);\n    if (typeof item === 'string') {\n      assertUnicodeScalarString(item);\n      return JSON.stringify(item);\n    }\n    if (typeof item === 'number') {\n      if (\n        !Number.isFinite(item)\n        || Object.is(item, -0)\n        || (Number.isInteger(item) && !Number.isSafeInteger(item))\n      ) {\n        throw new Error('canonical JSON requires finite, safe, non-negative-zero numbers');\n      }\n      return JSON.stringify(item);\n    }\n    if (item === undefined) throw new Error('canonical JSON does not support undefined');\n    if (typeof item !== 'object') {\n      throw new Error(`canonical JSON does not support ${typeof item}`);\n    }\n    if (ancestors.has(item)) throw new Error('canonical JSON does not support cycles');\n    ancestors.add(item);\n    try {\n      if (Array.isArray(item)) return `[${item.map(encode).join(',')}]`;\n      const prototype = Object.getPrototypeOf(item);\n      if (prototype !== Object.prototype && prototype !== null) {\n        throw new Error('canonical JSON supports only arrays and plain objects');\n      }\n      const entries = Object.entries(item as Record<string, unknown>)\n        .sort(([left], [right]) => codeUnitCompare(left, right));\n      return `{${entries.map(([key, child]) => {\n        assertUnicodeScalarString(key);\n        return `${JSON.stringify(key)}:${encode(child)}`;\n      }).join(',')}}`;\n    } finally {\n      ancestors.delete(item);\n    }","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/codex/src/harness/repository-state.ts#L111-L147","documentation":"This branch catches any remaining non-object value that is not null/boolean/string/number/undefined — in practice symbol, bigint, and function — and embeds its typeof in the message (e.g. 'canonical JSON does not support bigint'). JSON has no representation for these types, and silently stringifying them would produce non-canonical output, so they are rejected with the type named.","triggerScenarios":"Evidence containing BigInt hashes or 64-bit integer IDs from crypto/database clients (postgres int64, BSON Long); Symbol values or symbol-keyed data leaking through spreads; class methods enumerated into the payload.","commonSituations":"node:crypto or driver APIs returning BigInt; schemas parsed with bigint support; passing rich objects whose enumerable properties include bound functions.","solutions":["Convert bigint leaves to strings while building the payload (String(n) or n.toString())","Pass evidence through a JSON.stringify replacer pre-pass that stringifies bigint and drops symbols/functions","Type payloads as a JsonValue structure so the compiler rejects these types at the boundary"],"exampleFix":"// before\ncanonicalJson({ fileId: BigInt('9007199254740993') });\n\n// after\ncanonicalJson({ fileId: '9007199254740993' });","handlingStrategy":"type-guard","validationCode":"function toCanonicalValue(value: unknown): unknown {\n  if (typeof value === 'bigint') return value.toString();\n  if (typeof value === 'symbol' || typeof value === 'function') return undefined; // drop\n  if (Array.isArray(value)) return value.map(toCanonicalValue);\n  if (typeof value === 'object' && value !== null) {\n    return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, toCanonicalValue(v)]));\n  }\n  return value;\n}","typeGuard":"type CanonicalJsonValue = null | boolean | number | string | CanonicalJsonValue[] | { [key: string]: CanonicalJsonValue };\nfunction isCanonicalJsonValue(value: unknown): value is CanonicalJsonValue {\n  if (value === null || ['boolean', 'number', 'string'].includes(typeof value)) return true;\n  if (Array.isArray(value)) return value.every(isCanonicalJsonValue);\n  if (typeof value === 'object') {\n    return Object.getPrototypeOf(value) === Object.prototype\n      && Object.values(value).every(isCanonicalJsonValue);\n  }\n  return false;\n}","tryCatchPattern":"try {\n  return canonicalJson(payload);\n} catch (error) {\n  if (error instanceof Error && error.message.startsWith('canonical JSON does not support ')\n      && /bigint|symbol|function/.test(error.message)) {\n    return canonicalJson(toCanonicalValue(payload));\n  }\n  throw error;\n}","preventionTips":["Convert bigint to string at the driver boundary (postgres int64, BSON Long, crypto values)","Type evidence payloads as CanonicalJsonValue so symbols/functions fail to compile","Pass payloads through JSON.stringify with a replacer as a cheap pre-flight check"],"tags":["canonical-json","bigint","symbol","serialization","type-error"],"backgroundTag":"unsupported-json-type","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}