JuliusBrussee/caveman · error
native session key create
Error message
native session key create: %w
What it means
os.OpenFile(path, O_WRONLY|O_CREATE|O_EXCL, 0600) failed with an error other than os.ErrExist — the EEXIST first-startup race is handled separately just below, so this error means a genuinely unexpected create failure: EACCES or EROFS on the runtime dir, ENOSPC, or ENAMETOOLONG. It fires right after successful MkdirAll+Chmod, so permissions usually changed underneath (MAC policy denial, concurrent chmod, immutable attribute).
Solutions
- Check MAC denials: ausearch -m avc -ts recent or the AppArmor log for the runtime path
- lsattr -d <home>/runtime — if immutable, clear with chattr -i
- Verify dir state: ls -ld <home>/runtime (want 0700 and your uid)
- Re-run after fixing; the O_EXCL create is atomic and safe to retry
Defensive patterns
Strategy: validation
Validate before calling
dir := filepath.Join(home, "runtime")
if info, err := os.Stat(dir); err == nil {
if !info.IsDir() {
return fmt.Errorf("%s exists and is not a directory — remove it", dir)
}
if st, ok := info.Sys().(*syscall.Stat_t); ok && int(st.Uid) != os.Getuid() {
return fmt.Errorf("%s owned by uid %d — run: sudo chown -R %d:%d %s", dir, st.Uid, os.Getuid(), os.Getgid(), dir)
}
} else if !errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("cannot inspect %s: %w", dir, err)
}
// only now call nativeruntime.LoadOrCreateSessionKey(home) Type guard
func isPermissionErr(err error) bool {
return errors.Is(err, fs.ErrPermission)
} Try / catch
key, err := nativeruntime.LoadOrCreateSessionKey(home)
if err != nil {
if errors.Is(err, fs.ErrPermission) {
// dir perms changed under startup or MAC policy denies creation:
// check ausearch -m avc / AppArmor logs, then lsattr -d <home>/runtime
log.Print("create denied — inspect ownership, immutability, and MAC denials")
}
return err
} Prevention
- Audit SELinux/AppArmor policies before deploying to hardened hosts — creation denials land here
- Watch for concurrent processes tightening permissions on the runtime dir during startup
- Clear immutable attributes (chattr -i) on the caveman home before starting
- Pre-check directory ownership and type immediately before first key creation
When it happens
Trigger: SELinux or AppArmor denying file creation inside the runtime dir; a concurrent process tightening permissions between the chmod and the open; chattr +i on the directory; a read-only remount occurring mid-startup.
Common situations: Hardened RHEL/Ubuntu hosts with strict MAC policy; security agents racing process startups; containers where the directory came from a lower, read-only layer.
Related errors
- native session key chmod dir
- native session key chmod
- native session key mkdir
- sqlite parent is group/world writable
- : : inspect database parent
AI-assisted analysis of JuliusBrussee/caveman@766dce6b13 (2026-08-18).
Data as JSON: /api/errors/7bdeb1860dc0a568.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/internal/nativeruntime/marker.go:54
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600)
if err == nil {
if _, writeErr := file.Write(key); writeErr != nil {
_ = file.Close()
_ = os.Remove(path)
return nil, fmt.Errorf("native session key write: %w", writeErr)
}
if syncErr := file.Sync(); syncErr != nil {
_ = file.Close()
_ = os.Remove(path)
return nil, fmt.Errorf("native session key sync: %w", syncErr)
}
if closeErr := file.Close(); closeErr != nil {
return nil, fmt.Errorf("native session key close: %w", closeErr)
}
return key, nil
}
if !errors.Is(err, os.ErrExist) {
return nil, fmt.Errorf("native session key create: %w", err)
}
key, err = os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("native session key read: %w", err)
}
if len(key) != sessionKeyBytes {
return nil, fmt.Errorf("native session key length = %d, want %d", len(key), sessionKeyBytes)
}
if err := os.Chmod(path, 0o600); err != nil {
return nil, fmt.Errorf("native session key chmod: %w", err)
}
return key, nil
}
// SessionMarker builds model-temporary correlation context. Local proxy removes
// valid markers byte-surgically before provider inspection or forwarding.
func SessionMarker(key []byte, sessionID string) (string, error) {
if len(key) != sessionKeyBytes || sessionID == "" || len(sessionID) > 256 {View on GitHub (pinned to 766dce6b13)