{"record":{"id":"48c8db0f6cda0187","repo":"JuliusBrussee/caveman","slug":"native-runtime-unsupported-protocol-version-d","errorCode":null,"errorMessage":"native runtime: unsupported protocol version %d","messagePattern":"native runtime: unsupported protocol version (.+?)","errorType":"error_code","errorClass":"error","httpStatus":null,"severity":"error","filePath":"proxy/internal/nativeruntime/runtime.go","lineNumber":212,"sourceCode":"\tcase \"ccr-masking\":\n\t\treturn profile, profileFeatures{capture: true, mask: true}, nil\n\tcase \"cache-aware\":\n\t\treturn profile, profileFeatures{taskContract: true, compactState: true}, nil\n\tcase \"full-safe\", \"full-max\":\n\t\treturn profile, profileFeatures{taskContract: true, compactState: true, reuse: true, capture: true, mask: true, repository: true}, nil\n\tdefault:\n\t\treturn \"\", profileFeatures{}, fmt.Errorf(\"native runtime: unknown profile %q\", raw)\n\t}\n}\n\nfunc (r *Runtime) Handle(_ context.Context, request Request) (Response, error) {\n\tstarted := time.Now()\n\tsessionLock := r.sessionLock(request.Session.ID)\n\tsessionLock.Lock()\n\tdefer sessionLock.Unlock()\n\n\tif request.ProtocolVersion != ProtocolVersion {\n\t\treturn Response{}, fmt.Errorf(\"native runtime: unsupported protocol version %d\", request.ProtocolVersion)\n\t}\n\tif _, ok := eventTypes[request.Event.Type]; !ok {\n\t\treturn Response{}, fmt.Errorf(\"native runtime: unknown event %q\", request.Event.Type)\n\t}\n\tif strings.TrimSpace(request.Session.ID) == \"\" {\n\t\treturn Response{}, errors.New(\"native runtime: session id is required\")\n\t}\n\tpolicyMode := request.PolicyMode\n\tif policyMode == \"\" {\n\t\tpolicyMode = \"safe\"\n\t}\n\tif policyMode != \"record\" && policyMode != \"safe\" && policyMode != \"max\" {\n\t\treturn Response{}, fmt.Errorf(\"native runtime: unknown policy mode %q\", policyMode)\n\t}\n\trequest.PolicyMode = policyMode\n\tprofile, features, err := resolveProfile(request.Profile, policyMode)\n\tif err != nil {\n\t\treturn Response{}, err","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/df2ccd85c94ec3c8289cb62ac020d241ccfb0c60/proxy/internal/nativeruntime/runtime.go#L194-L230","documentation":"Handle validates every inbound Request before doing any work; the very first check compares request.ProtocolVersion against the runtime's exported ProtocolVersion constant. If the client speaks a different wire-protocol version than this native runtime binary, Handle refuses the request with this error instead of misinterpreting the payload. It is a hard compatibility gate between the caller (serveConn) and the runtime process.","triggerScenarios":"Any call to Handle (via serveConn) where request.ProtocolVersion != ProtocolVersion, e.g. a client built against protocol v1 sending to a runtime expecting v2, a stale ~/.caveman/bin runtime binary paired with a newer CLI, or hand-rolled IPC clients hardcoding an old version number.","commonSituations":"Upgrading the npm CLI (`caveman`) without rebuilding the local Go binaries via scripts/install-local-cli.sh (or vice versa); CAVEMAN_PROXY_BIN / CAVEMAN_*_BIN env overrides pointing at an old or third-party binary; mixing versions across machines with a shared ~/.caveman directory.","solutions":["Rebuild/reinstall the local Go binaries so both sides use the same protocol: run scripts/install-local-cli.sh (or install-local-cli.ps1) from the repo root.","Check for stray CAVEMAN_PROXY_BIN/CAVEMAN_*_BIN env overrides pointing at an outdated binary and remove or update them; run `caveman setup` to see per-binary status.","Upgrade or downgrade the npm CLI package so its expected protocol version matches the runtime binary.","If you own the client code, set request.ProtocolVersion to the runtime's exported ProtocolVersion constant instead of a literal."],"exampleFix":"// before: client hardcodes an old protocol version\nrequest := nativeruntime.Request{ProtocolVersion: 1, Session: session, Event: event}\n\n// after: always use the constant from the same package version\nrequest := nativeruntime.Request{ProtocolVersion: nativeruntime.ProtocolVersion, Session: session, Event: event}","handlingStrategy":"validation","validationCode":"// Before sending, confirm client and runtime agree on the protocol version.\nfunction validateRuntimeCompat(clientVersion: number, runtimeVersion: number): void {\n  if (clientVersion !== runtimeVersion) {\n    throw new Error(\n      `runtime protocol mismatch: client=${clientVersion} runtime=${runtimeVersion}; ` +\n      \"rebuild Go binaries (scripts/install-local-cli.sh) or update the CLI\",\n    );\n  }\n}\nvalidateRuntimeCompat(nativeruntime.ProtocolVersion, runtime.ProtocolVersion);","typeGuard":"func supportsProtocol(request Request) bool {\n\treturn request.ProtocolVersion == ProtocolVersion\n}","tryCatchPattern":"resp, err := runtime.Handle(ctx, request)\nif err != nil {\n\tvar unsupported * UnsupportedProtocolError\n\tif errors.Is(err, ErrUnsupportedProtocol) || strings.Contains(err.Error(), \"unsupported protocol version\") {\n\t\tlog.Fatalf(\"runtime/CLI version skew: %v — run scripts/install-local-cli.sh\", err)\n\t}\n\treturn err\n}","preventionTips":["Rebuild all local Go binaries after every CLI upgrade (scripts/install-local-cli.sh / .ps1); run `caveman setup` to confirm each binary resolves.","Audit CAVEMAN_*_BIN env overrides — stale paths to old binaries are the top cause of version skew.","Always reference nativeruntime.ProtocolVersion in client code; never hardcode a numeric version.","Pin CLI package and local binary builds to the same release when deploying across machines."],"tags":["go","ipc","version-mismatch","compatibility"],"backgroundTag":"protocol-version-mismatch","analyzedSha":"df2ccd85c94ec3c8289cb62ac020d241ccfb0c60","analyzedAt":"2026-08-31T22:10:17.934Z","contentChangedAt":"2026-08-31T22:10:17.934Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}