ruvnet/ruflo · error · TypeError

JCS canonicalization accepts only JSON-compatible plain obje

Error message

JCS canonicalization accepts only JSON-compatible plain objects

What it means

JCS canonicalizer guard: the value being serialized is neither a primitive nor an array nor a plain object (isRecord failed) — e.g. a Date, Map, class instance, or null-prototype object. JCS only defines canonical forms for JSON-compatible plain objects, so such values are rejected rather than coerced.

Source

Thrown at v3/@claude-flow/security/src/policy/product-plane.ts:1112

    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(',')}}`;
}

export function canonicalProductPlaneBytes(value: unknown): Uint8Array {
  return Buffer.from(canonicalizeProductPlane(value), 'utf8');
}

export function canonicalProductPlaneDigest(value: unknown): `sha256:${string}` {
  return `sha256:${createHash('sha256').update(canonicalProductPlaneBytes(value)).digest('hex')}`;

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Strip class instances, Maps, Sets, and functions before canonicalizing; convert them to plain JSON objects first.
  2. Use a serializer (e.g. JSON.parse(JSON.stringify(value)) with a replacer) to normalize non-plain objects into JSON-compatible shapes.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at v3/@claude-flow/security/src/policy/product-plane.ts:1112 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/9228656f0f59eda2. Report an issue: GitHub.