{"record":{"id":"8d361ec6b7ae39e8","repo":"JuliusBrussee/caveman","slug":"cave-harness-upstream-version-mismatch-8d361e","errorCode":"cave_${harness}_upstream_version_mismatch","errorMessage":"cave_${harness}_upstream_version_mismatch","messagePattern":"cave_(.+?)_upstream_version_mismatch","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/adapters.ts","lineNumber":592,"sourceCode":"\nfunction assertSupportedUpstream(\n  identity: HarnessAdapterIdentity,\n  expected: string,\n  harness: string,\n  pkg: string,\n): void {\n  // The pin is enforced against the INSTALLED version, and the caller's claimed\n  // upstreamVersion must match what is actually installed — a claim alone can no\n  // longer authorize execution.\n  const installed = installedPackageVersion(pkg);\n  if (installed === undefined) {\n    throw new Error(`cave_${harness}_upstream_version_unresolvable`);\n  }\n  if (installed !== expected) {\n    throw new Error(`cave_${harness}_upstream_version_unsupported`);\n  }\n  if (identity.upstreamVersion !== installed) {\n    throw new Error(`cave_${harness}_upstream_version_mismatch`);\n  }\n}\n\nfunction canonicalRecord(value: Readonly<Record<string, unknown>>): Readonly<Record<string, unknown>> {\n  let encoded: string;\n  try {\n    encoded = stableStringify(value);\n  } catch {\n    throw new Error(\"cave_harness_wire_contract_invalid\");\n  }\n  const decoded = JSON.parse(encoded) as unknown;\n  if (!isRecord(decoded)) throw new Error(\"cave_harness_wire_contract_invalid\");\n  return decoded;\n}\n\nfunction deepFreeze<T>(value: T): T {\n  if (value !== null && typeof value === \"object\") {\n    Object.freeze(value);","sourceCodeStart":574,"sourceCodeEnd":610,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/adapters.ts#L574-L610","documentation":"The installed harness version resolves and matches the adapter's pin, but the `upstreamVersion` the caller supplied in the harness identity does not equal the installed version. The pin chain requires lock, plan, installed package, and claimed identity to agree; a claim alone cannot authorize execution. This almost always means the identity object was built from a stale or hardcoded version string instead of the live runtime.","triggerScenarios":"Passing a `HarnessAdapterIdentity` with `upstreamVersion: \"7.0.40\"` while 7.0.43 is installed; caching an identity across an `npm install` that bumped the pinned-but-then-reinstalled package; building identity from a constant instead of reading the installed package version.","commonSituations":"Hardcoding the upstream version in app code and forgetting to update it after a reinstall; reusing a serialized identity from a previous session/lock file; CI image rebuilt with a patched harness version while the app config still names the old one.","solutions":["Update the `upstreamVersion` in the identity you pass to match the installed version reported in the error.","Better: derive the identity's `upstreamVersion` at runtime from the installed package (or obtain the identity from the framework) instead of hardcoding it.","After any dependency change, regenerate lock/plan artifacts that embed the upstream version."],"exampleFix":"// before\nconst identity = { upstreamVersion: \"7.0.40\", /* ... */ }; // installed is 7.0.43\n\n// after\nconst identity = { upstreamVersion: \"7.0.43\", /* ... */ };","handlingStrategy":"validation","validationCode":"import { readFileSync } from \"node:fs\";\nfunction installedVersion(pkg: string): string {\n  return JSON.parse(\n    readFileSync(fileURLToPath(import.meta.resolve(`${pkg}/package.json`)), \"utf8\"),\n  ).version as string;\n}\n// derive, never hardcode:\nconst identity = { upstreamVersion: installedVersion(\"ai\"), /* ... */ };","typeGuard":null,"tryCatchPattern":"try {\n  await adapter.run(request);\n} catch (err) {\n  if (err instanceof Error && err.message.endsWith(\"_upstream_version_mismatch\")) {\n    // rebuild identity from the installed version and retry once\n  }\n}","preventionTips":["Never hardcode upstreamVersion; resolve it from the installed package at runtime.","Regenerate lock/plan artifacts after any dependency change.","Treat serialized identities as stale after reinstalling dependencies."],"tags":["adapter","version-pin","identity","stale-config"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}