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

  1. Run the coding agent in an interactive user session (normal user process) so the process token carries a user SID.
  2. Inspect the wrapped GetTokenUser error (native runtime current user SID: %w) for the underlying OS failure code.
  3. If running as a service, configure the service to log on as a real user account rather than a synthetic identity.
  4. 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

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


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)