JuliusBrussee/caveman · error
native session key random: %w
Error message
native session key random: %w
What it means
LoadOrCreateSessionKey draws 32 bytes from crypto/rand for the new session key. rand.Read practically never fails on Linux (it can block until the pool is ready but errors only on a broken reader), so this error almost always indicates an extremely early boot entropy state or an OS/driver-level problem with the random device.
Source
Thrown at proxy/internal/nativeruntime/marker.go:34
const sessionKeyBytes = 32
var markerPattern = regexp.MustCompile(`\[\[caveman-session-v1 sid="([A-Za-z0-9_-]{1,384})" sig="([0-9a-f]{64})"\]\]`)
// LoadOrCreateSessionKey returns one user-only HMAC key shared by CLI adapters
// and local proxy. O_EXCL makes concurrent first startup converge on one key.
func LoadOrCreateSessionKey(home string) ([]byte, error) {
dir := filepath.Join(home, "runtime")
if err := os.MkdirAll(dir, 0o700); err != nil {
return nil, fmt.Errorf("native session key mkdir: %w", err)
}
if err := os.Chmod(dir, 0o700); err != nil {
return nil, fmt.Errorf("native session key chmod dir: %w", err)
}
path := filepath.Join(dir, "session.key")
key := make([]byte, sessionKeyBytes)
if _, err := rand.Read(key); err != nil {
return nil, fmt.Errorf("native session key random: %w", err)
}
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
}View on GitHub (pinned to 27d5a3981a)
Solutions
- Simply retry after a moment — once the kernel CRNG is seeded this succeeds
- Ensure the container/chroot exposes a working /dev/urandom and allows getrandom(2)
- Use a modern base image; very old kernels lacked getrandom and fall back to weaker paths
Defensive patterns
Strategy: retry
Try / catch
var key []byte
err := backoffRetry(3, func() error {
var e error
key, e = nativeruntime.LoadOrCreateSessionKey(home)
return e
}) // entropy failures self-heal once the kernel CRNG is seeded Prevention
- Let containers boot briefly before first start, or seed entropy (virtio-rng)
- Keep /dev/urandom accessible in chroots/seccomp profiles
- Use current base images with getrandom(2) support
When it happens
Trigger: First process executed in a freshly booted minimal VM/container before the CRNG is seeded; /dev/urandom unavailable due to a broken chroot or seccomp policy; hardware/kernel fault.
Common situations: CI containers or embedded images booting and immediately starting the proxy; overly restrictive sandboxes blocking getrandom(2).
Related errors
- nonce entropy: %w
- native session key mkdir: %w
- native session key chmod dir: %w
- native session key write: %w
- native session key sync: %w
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/520db03ad275b612.
Report an issue: GitHub.