{"record":{"id":"7611c89d436bd3ac","repo":"JuliusBrussee/caveman","slug":"native-runtime-named-pipe-accept-w","errorCode":null,"errorMessage":"native runtime named-pipe accept: %w","messagePattern":"native runtime named-pipe accept: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/nativeruntime/server_windows.go","lineNumber":68,"sourceCode":"\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()\n\tgo func() {\n\t\t<-ctx.Done()\n\t\t_ = listener.Close()\n\t}()\n\tfor {\n\t\tconn, err := listener.Accept()\n\t\tif err != nil {\n\t\t\tif ctx.Err() != nil || errors.Is(err, net.ErrClosed) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"native runtime named-pipe accept: %w\", err)\n\t\t}\n\t\tgo serveConn(ctx, conn, runtime)\n\t}\n}\n","sourceCodeStart":50,"sourceCodeEnd":73,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/proxy/internal/nativeruntime/server_windows.go#L50-L73","documentation":"Returned when listener.Accept() fails on the Windows named pipe and neither the context is cancelled nor the error is net.ErrClosed. This is an unexpected accept failure on the pipe listener — typically a broken pipe instance or OS-level error, since intentional shutdown is filtered by the ctx.Err()/ErrClosed checks.","triggerScenarios":"Long-running Serve on Windows where the underlying named pipe instance is destroyed by an external handle close, or a Win32 accept error (pipe disconnected in an unrecoverable state) occurs while ctx is still live.","commonSituations":"Tooling (Process Explorer, debuggers) or AV software closing pipe handles; a go-winio version mismatch with the installed Windows version; the process running under a context that loses the pipe namespace after a session change (fast user switching, RDP disconnect).","solutions":["Update go-winio to the latest version — accept/retry logic around broken pipe instances has seen fixes","Exclude the caveman pipe from AV/EDR scanning and prevent external tools from closing its handles","Add a resilience wrapper: on error, close the listener and re-enter Serve while ctx is alive","Check Windows Event Log for pipe/FS errors if it recurs"],"exampleFix":"// before: any non-shutdown accept error terminates Serve\nreturn fmt.Errorf(\"native runtime named-pipe accept: %w\", err)\n\n// after: supervise the server loop so a transient accept failure restarts the pipe\nfor {\n    if err := nativeruntime.Serve(ctx, home, rt); err != nil && ctx.Err() == nil {\n        log.Warn(\"native runtime exited, restarting\", \"error\", err)\n        time.Sleep(time.Second)\n        continue\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":null,"tryCatchPattern":"for {\n    err := nativeruntime.Serve(ctx, home, rt)\n    if err == nil || ctx.Err() != nil { return err }\n    var ne net.Error\n    if errors.As(err, &ne) || strings.Contains(err.Error(), \"named-pipe accept\") {\n        log.Warn(\"pipe accept failed; recreating listener\", \"error\", err)\n        select { case <-time.After(time.Second): case <-ctx.Done(): return ctx.Err() }\n        continue\n    }\n    return err\n}","preventionTips":["Supervise the Serve loop so transient pipe errors recover without operator action","Update go-winio regularly; accept-path robustness improves between releases","Prevent external tools from closing pipe handles"],"tags":["windows","named-pipe","accept","go"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}