ruvnet/ruflo · error · TypeError
JCS canonicalization rejects sparse arrays
Error message
JCS canonicalization rejects sparse arrays
What it means
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.
Source
Thrown at v3/@claude-flow/security/src/policy/product-plane.ts:1105
* Non-finite numbers, sparse arrays, undefined values, non-plain objects, and
* invalid Unicode are rejected instead of being silently coerced.
*/
export function canonicalizeProductPlane(value: unknown): string {
if (value === null) return 'null';
if (typeof value === 'boolean') return value ? 'true' : 'false';
if (typeof value === 'string') {
assertUnicodeScalarString(value);
return JSON.stringify(value);
}
if (typeof value === 'number') {
if (!Number.isFinite(value)) throw new TypeError('JCS canonicalization rejects non-finite numbers');
return JSON.stringify(value);
}
if (Array.isArray(value)) {
const items: string[] = [];
for (let index = 0; index < value.length; index++) {
if (!Object.prototype.hasOwnProperty.call(value, index)) {
throw new TypeError('JCS canonicalization rejects sparse arrays');
}
items.push(canonicalizeProductPlane(value[index]));
}
return `[${items.join(',')}]`;
}
if (!isRecord(value)) {
throw new TypeError('JCS canonicalization accepts only JSON-compatible plain objects');
}
const entries: string[] = [];
for (const key of Object.keys(value).sort()) {
assertUnicodeScalarString(key);
if (value[key] === undefined) {
throw new TypeError('JCS canonicalization rejects undefined object values');
}
entries.push(`${JSON.stringify(key)}:${canonicalizeProductPlane(value[key])}`);
}
return `{${entries.join(',')}}`;
}View on GitHub (pinned to fa13ee4ad6)
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.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at v3/@claude-flow/security/src/policy/product-plane.ts:1105 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/2cb70d5c0d19f5ec.
Report an issue: GitHub.