JuliusBrussee/caveman · error

native session key write: %w

Error message

native session key write: %w

What it means

The freshly generated 32-byte key could not be written to <home>/runtime/session.key (O_CREAT|O_EXCL, 0600). On failure the partial file is closed and removed, so no corrupt key is left behind. Disk full, quota, or I/O errors are the usual causes — permission issues on the directory typically surface as the separate 'create' error instead.

Source

Thrown at proxy/internal/nativeruntime/marker.go:41

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
	}
	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)
	}

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Free disk space / inodes (df -h, df -i) and start again — the cleanup makes this safe to retry
  2. Raise the user's quota if that is the reported cause
  3. If it recurs on NFS/overlay storage, move home to local disk
Defensive patterns

Strategy: retry

Validate before calling

func diskAvailable(path string) bool {
    var st syscall.Statfs_t
    if err := syscall.Statfs(path, &st); err != nil {
        return false
    }
    return st.Bavail*uint64(st.Bsize) > 1<<20 // >1MiB free
}

Try / catch

key, err := nativeruntime.LoadOrCreateSessionKey(home)
if err != nil && strings.Contains(err.Error(), "session key write") {
    // partial file is already cleaned up; free space then retry once
    if freed := freeDisk(home); freed {
        key, err = nativeruntime.LoadOrCreateSessionKey(home)
    }
}

Prevention

When it happens

Trigger: Disk full or inode exhaustion at the moment of first startup; quota exceeded for the user; transient NFS/overlayfs write failure.

Common situations: Long-lived machines or CI runners with full disks; Docker overlay2 thin-provision exhaustion.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/5c799a10655ca35d. Report an issue: GitHub.