{"record":{"id":"a0a0fe84ae40b3ab","repo":"JuliusBrussee/caveman","slug":"unsupported-version","errorCode":"unsupported_version","errorMessage":"unsupported_version","messagePattern":"unsupported_version","errorType":"error_code","errorClass":"MiddlewareError","httpStatus":null,"severity":"error","filePath":"packages/sdk/typescript/src/middleware/validate.ts","lineNumber":23,"sourceCode":"export async function sha256(text: string): Promise<string> {\n  return Array.from(new Uint8Array(await crypto.subtle.digest('SHA-256', encoder.encode(text))), b => b.toString(16).padStart(2, '0')).join('');\n}\nexport const isHash = (s: unknown): s is string => typeof s === 'string' && /^[a-f0-9]{64}$/.test(s);\nexport const isToken = (s: unknown): s is string => typeof s === 'string' && /^[a-zA-Z0-9._:/-]{1,256}$/.test(s);\nconst integer = (n: unknown): n is number => Number.isSafeInteger(n) && (n as number) >= 0;\nexport function scopeKey(scope: Scope): string {\n  if (![scope.namespace, scope.session_id, scope.branch_id, scope.cache_epoch].every(isToken)) throw new MiddlewareError('invalid_scope');\n  return JSON.stringify([scope.namespace, scope.session_id, scope.branch_id, scope.cache_epoch]);\n}\nexport class MiddlewareError extends Error {\n  constructor(readonly code: string) { super(`Caveman middleware: ${code}`); this.name = 'MiddlewareError'; }\n}\nexport function validateCapabilities(value: unknown): Capabilities {\n  const c = value as Capabilities;\n  if (!c || c.schema_version !== 1 || !isToken(c.policy_revision) || typeof c.runtime_build !== 'string' ||\n    !['record', 'compress'].includes(c.mode) || !Array.isArray(c.transforms) || c.transforms.length > 128 ||\n    !c.limits || !Object.values(c.limits).every(n => integer(n) && n > 0) ||\n    !integer(c.retention_seconds) || typeof c.recovery !== 'boolean' || typeof c.persistent !== 'boolean') throw new MiddlewareError('unsupported_version');\n  const ids = new Set<string>();\n  for (const t of c.transforms) {\n    if (!isToken(t.transform_id) || ids.has(t.transform_id) || !isToken(t.implementation_version) || !Array.isArray(t.eligible_segment_kinds) ||\n      !['exact_ccr', 'none'].includes(t.recovery) || t.deterministic !== true) throw new MiddlewareError('unknown_capability');\n    ids.add(t.transform_id);\n  }\n  return c;\n}\n\n/** Validate every leaf before an adapter is allowed to apply any of them. */\nexport async function validatePlan(value: unknown, request: OptimizeRequest, inputDigest: string, caps: Capabilities): Promise<Plan> {\n  const p = value as Plan;\n  const invalid = () => { throw new MiddlewareError('invalid_plan'); };\n  if (!p || p.schema_version !== 1 || p.request_id !== request.request_id || p.input_digest !== inputDigest ||\n    p.policy_revision !== request.policy.revision || !isHash(p.replacement_set_id) || !['optimized','bypassed','record'].includes(p.status) ||\n    !isToken(p.reason) || !Array.isArray(p.replacements) || !Array.isArray(p.skipped) || !p.measurement || !p.stability || !p.recovery) invalid();\n  const m = p.measurement;\n  if (m.basis !== 'inferred' || m.scope !== 'segment' || m.verified_saved_usd !== 0 || typeof m.tokenizer !== 'string' ||","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/sdk/typescript/src/middleware/validate.ts#L5-L41","documentation":"MiddlewareError('unsupported_version') is thrown by validateCapabilities() when the runtime's /capabilities response fails structural validation: schema_version !== 1, missing/invalid policy_revision or runtime_build, an unrecognized mode, malformed transforms array (>128 entries), invalid limits or retention_seconds, or wrong-typed recovery/persistent flags. It indicates the server's capability advertisement is not compatible with this SDK version.","triggerScenarios":"Connecting to a runtime built for a different schema_version (not 1); an old SDK against a newer runtime or vice versa; a proxy or mock returning a non-capabilities JSON document; a runtime bug producing a malformed capabilities payload.","commonSituations":"Upgrading the SDK without upgrading the bundled runtime (or the reverse); pointing the middleware at an arbitrary HTTP server that is not the Caveman runtime; an intermediary caching a stale capabilities document.","solutions":["Align SDK and runtime versions so schema_version is 1 on both sides","Verify the endpoint actually serves the Caveman capabilities document (curl the capabilities path)","Clear any proxy/CDN cache serving stale capabilities","Catch MiddlewareError code 'unsupported_version' and surface an upgrade message to operators"],"exampleFix":"// before\ncreateMiddlewareRuntime({ endpoint: 'http://127.0.0.1:3000' }) // wrong service, old schema\n// after\ncreateMiddlewareRuntime({ endpoint: 'http://127.0.0.1:8787' }) // matching runtime, schema_version 1\nawait runtime.ready();","handlingStrategy":"try-catch","validationCode":"const caps = await fetch(capsUrl).then(r => r.json()).catch(() => null);\nif (caps?.schema_version !== 1) throw new Error('runtime/SDK schema mismatch — align versions');","typeGuard":null,"tryCatchPattern":"try { await runtime.ready(); } catch (e) { if (e instanceof MiddlewareError && e.code === 'unsupported_version') { alertOperator('upgrade runtime to match SDK schema_version 1'); } throw e; }","preventionTips":["Pin and upgrade SDK and runtime versions together","Confirm the endpoint is the Caveman runtime, not another HTTP service","Bypass caches/proxies for the capabilities endpoint or set short TTLs"],"tags":["versioning","compatibility","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}