{"record":{"id":"dc59aab179b48c39","repo":"JuliusBrussee/caveman","slug":"native-runtime-store-is-required-dc59aa","errorCode":null,"errorMessage":"native runtime: store is required","messagePattern":"native runtime: store is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/nativeruntime/server_windows.go","lineNumber":39,"sourceCode":"\tabsolute, err := filepath.Abs(home)\n\tif err != nil {\n\t\tabsolute = home\n\t}\n\tnormalized := strings.ToLower(filepath.Clean(absolute))\n\tsum := sha256.Sum256([]byte(normalized))\n\treturn `\\\\.\\pipe\\caveman-native-` + hex.EncodeToString(sum[:8])\n}\n\nfunc dialNativeRuntime(ctx context.Context, home string) (net.Conn, error) {\n\treturn winio.DialPipeContext(ctx, SocketPath(home))\n}\n\n// Serve exposes the same bounded JSON protocol over a user-only Windows named\n// pipe. go-winio rejects remote clients at pipe creation; explicit owner SID\n// ACL prevents another local user from attaching.\nfunc Serve(ctx context.Context, home string, runtime *Runtime) error {\n\tif runtime == nil || runtime.store == nil {\n\t\treturn errors.New(\"native runtime: store is required\")\n\t}\n\tuser, err := windows.GetCurrentProcessToken().GetTokenUser()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"native runtime current user SID: %w\", err)\n\t}\n\tif user == nil || user.User.Sid == nil {\n\t\treturn errors.New(\"native runtime current user SID: unavailable\")\n\t}\n\tsddl := \"D:P(A;;GA;;;\" + user.User.Sid.String() + \")\"\n\tlistener, err := winio.ListenPipe(SocketPath(home), &winio.PipeConfig{\n\t\tSecurityDescriptor: sddl,\n\t\tInputBufferSize:    maxRequestBytes,\n\t\tOutputBufferSize:   maxRequestBytes,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"native runtime named-pipe listen: %w\", err)\n\t}\n\tdefer listener.Close()","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/766dce6b1394ebb56a3090748d5a0240a5aefb36/proxy/internal/nativeruntime/server_windows.go#L21-L57","documentation":"This guard fires in nativeruntime.Serve on Windows before the named-pipe listener is created. The pipe server answers requests by reading from the Runtime's backing store (Runtime.store, injected via nativeruntime.New/NewWithReceipts), so Serve refuses to start when runtime is nil or its store was never wired. A pipe without the store could not serve the protocol at all, so this is a fail-fast wiring check.","triggerScenarios":"Calling nativeruntime.Serve(ctx, home, runtime) with a nil *Runtime, or with a Runtime built as a struct literal (zero value, store == nil) instead of nativeruntime.New(store) / NewWithReceipts(store, dir). Typically happens when the store-open step failed earlier, the error was ignored, and wiring continued with a nil handle.","commonSituations":"Startup code that ignores the error from opening the SQLite/ccr store and passes the result anyway; refactors that move store construction into another function; unit tests that instantiate &Runtime{} directly to save setup.","solutions":["Find the Serve call site and build the runtime with nativeruntime.New(store) (or NewWithReceipts), passing a store handle that opened successfully.","Propagate the store-open error and abort startup instead of continuing with a nil store.","In wiring/main, log store-open failures distinctly from named-pipe listen failures so this guard never fires in production."],"exampleFix":"// before\nruntime := &nativeruntime.Runtime{} // zero value: store == nil\nerr := nativeruntime.Serve(ctx, home, runtime)\n\n// after\nstore, err := openCCRSpecStore(home) // must succeed\nif err != nil {\n\treturn fmt.Errorf(\"open ccr store: %w\", err)\n}\nerr = nativeruntime.Serve(ctx, home, nativeruntime.New(store))","handlingStrategy":"validation","validationCode":"// Before Serve: prove the runtime was constructed with a real store.\nif runtime == nil {\n\treturn errors.New(\"nativeruntime.Serve: runtime is nil; build with nativeruntime.New(store)\")\n}\n// Runtime.store is unexported, so the only safe construction is the constructor:\n// ensure the store opened successfully BEFORE calling New.\nstore, err := openStoreOrFail(home)\nif err != nil {\n\treturn err\n}\nruntime = nativeruntime.New(store)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never construct nativeruntime.Runtime as a struct literal; always use New/NewWithReceipts with a store whose open succeeded.","Treat store-open errors as fatal in startup wiring instead of continuing with a nil handle.","Add a smoke test that boots Serve with the real wiring so a nil store fails in CI, not on a user machine."],"tags":["windows","named-pipe","nil-check","initialization","native-runtime"],"backgroundTag":"missing-required-dependency","analyzedSha":"766dce6b1394ebb56a3090748d5a0240a5aefb36","analyzedAt":"2026-08-18T03:14:35.516Z","contentChangedAt":"2026-08-18T03:14:35.516Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}