{"record":{"id":"2cb70d5c0d19f5ec","repo":"ruvnet/ruflo","slug":"jcs-canonicalization-rejects-sparse-arrays","errorCode":null,"errorMessage":"JCS canonicalization rejects sparse arrays","messagePattern":"JCS canonicalization rejects sparse arrays","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/security/src/policy/product-plane.ts","lineNumber":1105,"sourceCode":" * Non-finite numbers, sparse arrays, undefined values, non-plain objects, and\n * invalid Unicode are rejected instead of being silently coerced.\n */\nexport function canonicalizeProductPlane(value: unknown): string {\n  if (value === null) return 'null';\n  if (typeof value === 'boolean') return value ? 'true' : 'false';\n  if (typeof value === 'string') {\n    assertUnicodeScalarString(value);\n    return JSON.stringify(value);\n  }\n  if (typeof value === 'number') {\n    if (!Number.isFinite(value)) throw new TypeError('JCS canonicalization rejects non-finite numbers');\n    return JSON.stringify(value);\n  }\n  if (Array.isArray(value)) {\n    const items: string[] = [];\n    for (let index = 0; index < value.length; index++) {\n      if (!Object.prototype.hasOwnProperty.call(value, index)) {\n        throw new TypeError('JCS canonicalization rejects sparse arrays');\n      }\n      items.push(canonicalizeProductPlane(value[index]));\n    }\n    return `[${items.join(',')}]`;\n  }\n  if (!isRecord(value)) {\n    throw new TypeError('JCS canonicalization accepts only JSON-compatible plain objects');\n  }\n  const entries: string[] = [];\n  for (const key of Object.keys(value).sort()) {\n    assertUnicodeScalarString(key);\n    if (value[key] === undefined) {\n      throw new TypeError('JCS canonicalization rejects undefined object values');\n    }\n    entries.push(`${JSON.stringify(key)}:${canonicalizeProductPlane(value[key])}`);\n  }\n  return `{${entries.join(',')}}`;\n}","sourceCodeStart":1087,"sourceCodeEnd":1123,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/security/src/policy/product-plane.ts#L1087-L1123","documentation":"JCS canonicalizer guard: while serializing an array, an index below length has no own property, i.e. the array is sparse (has holes). RFC 8785 canonical JSON has no representation for holes, and silently coercing them to null would change what gets signed/hashed, so canonicalization is refused.","triggerScenarios":"Thrown at v3/@claude-flow/security/src/policy/product-plane.ts:1105 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Remove holes from the array before canonicalizing: use Array.from(arr) or arr.map(String) to materialize every index.","Validate input with a pre-check that rejects sparse arrays (e.g. arr.length !== Object.keys(arr).length) and restructure data to dense arrays."],"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-14T00:17:10.932Z"}