{"record":{"id":"5c799a10655ca35d","repo":"JuliusBrussee/caveman","slug":"native-session-key-write-w","errorCode":null,"errorMessage":"native session key write: %w","messagePattern":"native session key write: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/nativeruntime/marker.go","lineNumber":41,"sourceCode":"func LoadOrCreateSessionKey(home string) ([]byte, error) {\n\tdir := filepath.Join(home, \"runtime\")\n\tif err := os.MkdirAll(dir, 0o700); err != nil {\n\t\treturn nil, fmt.Errorf(\"native session key mkdir: %w\", err)\n\t}\n\tif err := os.Chmod(dir, 0o700); err != nil {\n\t\treturn nil, fmt.Errorf(\"native session key chmod dir: %w\", err)\n\t}\n\tpath := filepath.Join(dir, \"session.key\")\n\tkey := make([]byte, sessionKeyBytes)\n\tif _, err := rand.Read(key); err != nil {\n\t\treturn nil, fmt.Errorf(\"native session key random: %w\", err)\n\t}\n\tfile, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o600)\n\tif err == nil {\n\t\tif _, writeErr := file.Write(key); writeErr != nil {\n\t\t\t_ = file.Close()\n\t\t\t_ = os.Remove(path)\n\t\t\treturn nil, fmt.Errorf(\"native session key write: %w\", writeErr)\n\t\t}\n\t\tif syncErr := file.Sync(); syncErr != nil {\n\t\t\t_ = file.Close()\n\t\t\t_ = os.Remove(path)\n\t\t\treturn nil, fmt.Errorf(\"native session key sync: %w\", syncErr)\n\t\t}\n\t\tif closeErr := file.Close(); closeErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"native session key close: %w\", closeErr)\n\t\t}\n\t\treturn key, nil\n\t}\n\tif !errors.Is(err, os.ErrExist) {\n\t\treturn nil, fmt.Errorf(\"native session key create: %w\", err)\n\t}\n\tkey, err = os.ReadFile(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"native session key read: %w\", err)\n\t}","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/proxy/internal/nativeruntime/marker.go#L23-L59","documentation":"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.","triggerScenarios":"Disk full or inode exhaustion at the moment of first startup; quota exceeded for the user; transient NFS/overlayfs write failure.","commonSituations":"Long-lived machines or CI runners with full disks; Docker overlay2 thin-provision exhaustion.","solutions":["Free disk space / inodes (df -h, df -i) and start again — the cleanup makes this safe to retry","Raise the user's quota if that is the reported cause","If it recurs on NFS/overlay storage, move home to local disk"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"func diskAvailable(path string) bool {\n    var st syscall.Statfs_t\n    if err := syscall.Statfs(path, &st); err != nil {\n        return false\n    }\n    return st.Bavail*uint64(st.Bsize) > 1<<20 // >1MiB free\n}","typeGuard":null,"tryCatchPattern":"key, err := nativeruntime.LoadOrCreateSessionKey(home)\nif err != nil && strings.Contains(err.Error(), \"session key write\") {\n    // partial file is already cleaned up; free space then retry once\n    if freed := freeDisk(home); freed {\n        key, err = nativeruntime.LoadOrCreateSessionKey(home)\n    }\n}","preventionTips":["Alert on low disk/inodes on volumes holding the caveman home","Retry is safe: failure paths remove the partial key file","Keep home off quota-constrained network volumes"],"tags":["filesystem","disk-full","nativeruntime","session-key"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}