JuliusBrussee/caveman · error
native runtime current user SID: unavailable
Error message
native runtime current user SID: unavailable
What it means
To build the owner-only named-pipe ACL, Serve fetches the current process token's user SID. If GetTokenUser returns an error, or the returned token user or SID is nil, Serve cannot construct a secure SDDL descriptor and refuses to create an unprotected pipe.
Solutions
- Run the coding agent in an interactive user session (normal user process) so the process token carries a user SID.
- Inspect the wrapped GetTokenUser error (native runtime current user SID: %w) for the underlying OS failure code.
- If running as a service, configure the service to log on as a real user account rather than a synthetic identity.
- As a workaround, disable the Windows named-pipe runtime surface if the environment cannot provide a user token.
Example fix
// before
// agent started as Windows service without a user token
// after
// configure service logon as a user account, or skip:
if err := nativeruntime.Serve(ctx, home, rt); err != nil {
log.Warnf("native runtime disabled: %v", err)
} Defensive patterns
Strategy: fallback
Validate before calling
u, err := windows.GetCurrentProcessToken().GetTokenUser()
if err != nil || u == nil || u.User.Sid == nil {
// cannot build owner-only ACL; skip pipe serving
} Type guard
func hasUserSID() bool {
u, err := windows.GetCurrentProcessToken().GetTokenUser()
return err == nil && u != nil && u.User != nil && u.User.Sid != nil
} Try / catch
if err := nativeruntime.Serve(ctx, home, rt); err != nil {
if strings.Contains(err.Error(), "SID") {
log.Warnf("native runtime unavailable without user token: %v", err)
return nil
}
return err
} Prevention
- Run the agent as an interactive user process, not a synthetic service identity
- Avoid impersonation contexts that strip token user info
- Feature-detect SID availability before enabling the pipe runtime
When it happens
Trigger: windows.GetCurrentProcessToken().GetTokenUser() fails, or returns user == nil / user.User.Sid == nil — e.g. running in a service/session context without a proper user token, restricted sandbox, or exotic Windows security configurations.
Common situations: Running the agent as a Windows service under an account with a stripped token; executing inside restricted job objects/containers where the token query is denied; unusual impersonation contexts in tests.
Understand the failure class
Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.
Related errors
- inspect sqlite parent ACL
- native runtime current user SID
- sqlite parent grants broad Windows write access
- sqlite parent has no restrictive DACL
- sqlite parent has no security descriptor
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/abf55e94e407d85a.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/internal/nativeruntime/server_windows.go:46
}
func dialNativeRuntime(ctx context.Context, home string) (net.Conn, error) {
return winio.DialPipeContext(ctx, SocketPath(home))
}
// Serve exposes the same bounded JSON protocol over a user-only Windows named
// pipe. go-winio rejects remote clients at pipe creation; explicit owner SID
// ACL prevents another local user from attaching.
func Serve(ctx context.Context, home string, runtime *Runtime) error {
if runtime == nil || runtime.store == nil {
return errors.New("native runtime: store is required")
}
user, err := windows.GetCurrentProcessToken().GetTokenUser()
if err != nil {
return fmt.Errorf("native runtime current user SID: %w", err)
}
if user == nil || user.User.Sid == nil {
return errors.New("native runtime current user SID: unavailable")
}
sddl := "D:P(A;;GA;;;" + user.User.Sid.String() + ")"
listener, err := winio.ListenPipe(SocketPath(home), &winio.PipeConfig{
SecurityDescriptor: sddl,
InputBufferSize: maxRequestBytes,
OutputBufferSize: maxRequestBytes,
})
if err != nil {
return fmt.Errorf("native runtime named-pipe listen: %w", err)
}
defer listener.Close()
go func() {
<-ctx.Done()
_ = listener.Close()
}()
for {
conn, err := listener.Accept()
if err != nil {View on GitHub (pinned to 3ee70a1026)