JuliusBrussee/caveman · error · Error

cave_context_ir_invalid

cave_context_ir_invalid

Error message

cave_context_ir_invalid

What it means

contextIRFromWire is the deserialization boundary for the Context IR format. The envelope must be a record with exactly the keys schema_version and segments, schema_version must be 1, and segments must be an array. Any other shape — including forward-compatible future versions — is rejected as cave_context_ir_invalid.

Source

Thrown at packages/agent/src/context-ir.ts:85

      stability: segment.stability,
      safety: segment.safety,
      priority: segment.priority,
      recovery: segment.recovery,
      cache_region: segment.cacheRegion,
      privacy: segment.privacy,
      opaque: segment.opaque,
      ...(segment.ttlTurns === undefined ? {} : { ttl_turns: segment.ttlTurns }),
      provenance_digest: segment.provenanceDigest,
      token_count: segment.tokenCount,
      body_handle: segment.bodyHandle,
    })),
  };
}

export function contextIRFromWire(value: unknown): ContextIR {
  if (!isRecord(value) || !exactKeys(value, ["schema_version", "segments"]) ||
      value.schema_version !== 1 || !Array.isArray(value.segments)) {
    throw new Error("cave_context_ir_invalid");
  }
  const segments = value.segments.map((item): ContextSegment => {
    const required = [
      "id", "kind", "stability", "safety", "priority", "recovery", "cache_region",
      "privacy", "opaque", "provenance_digest", "token_count", "body_handle",
    ];
    if (!isRecord(item) ||
        !(exactKeys(item, required) || exactKeys(item, [...required, "ttl_turns"])) ||
        typeof item.id !== "string" || item.id.length === 0 ||
        !known(item.kind, ["instruction", "user_intent", "tool_schema", "skill", "memory", "history", "tool_result", "artifact", "error", "output_contract"]) ||
        !known(item.stability, ["build", "session", "turn"]) ||
        !known(item.safety, ["S0", "S1", "S2", "S3", "S4"]) ||
        !known(item.priority, ["required", "high", "normal", "low"]) ||
        !known(item.recovery, ["none", "exact_ccr", "source_ref", "recompute"]) ||
        !known(item.cache_region, ["frozen_prefix", "live_zone", "uncached"]) ||
        !known(item.privacy, ["content_blind", "local_sensitive", "connected_allowed"]) ||
        typeof item.opaque !== "boolean" ||
        !/^[0-9a-f]{64}$/.test(String(item.provenance_digest)) ||

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Regenerate the wire payload with contextIRToWire from the same package version and retry
  2. Pin all services that exchange Context IR to the same package version so schema_version matches
  3. Parse the JSON once before passing (typeof value === 'string' ? JSON.parse(value) : value)
  4. Add a version dispatch layer: read schema_version first and migrate older shapes before calling contextIRFromWire

Example fix

// before
const ir = contextIRFromWire(raw); // raw had schema_version: 2 or extra keys

// after: re-serialize with the current codec
const wire = contextIRToWire(ir);
const roundTripped = contextIRFromWire(JSON.parse(JSON.stringify(wire)));
Defensive patterns

Strategy: type-guard

Validate before calling

function looksLikeContextIREnvelope(v: unknown): boolean {
  return typeof v === "object" && v !== null &&
    Object.keys(v).length === 2 &&
    (v as any).schema_version === 1 &&
    Array.isArray((v as any).segments);
}

Type guard

function isContextIRWire(v: unknown): v is { schema_version: 1; segments: unknown[] } {
  return isRecord(v) &&
    exactKeysCheck(v, ["schema_version", "segments"]) &&
    v.schema_version === 1 && Array.isArray(v.segments);
}

Try / catch

try {
  const ir = contextIRFromWire(payload);
} catch (err) {
  if (err instanceof Error && err.message === "cave_context_ir_invalid") {
    // treat as a version/shape mismatch: regenerate payload with contextIRToWire
    throw new Error(`Context IR payload rejected; regenerate with the current codec (schema_version=${(payload as any)?.schema_version})`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Feeding contextIRFromWire JSON that: is not an object; carries extra top-level keys; has schema_version 2 or '1' (string); has segments as an object rather than array; or was double-encoded (a JSON string of JSON).

Common situations: Persisted IR from a newer/older package version with a different schema_version; hand-crafted fixtures in tests; payloads relayed through queues that JSON.stringify twice; renamed top-level fields during refactors.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/1708b9b7400b108b. Report an issue: GitHub.