{"record":{"id":"55915921db91b91c","repo":"JuliusBrussee/caveman","slug":"native-session-key-close-w","errorCode":null,"errorMessage":"native session key close: %w","messagePattern":"native session key close: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/nativeruntime/marker.go","lineNumber":49,"sourceCode":"\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}\n\tif len(key) != sessionKeyBytes {\n\t\treturn nil, fmt.Errorf(\"native session key length = %d, want %d\", len(key), sessionKeyBytes)\n\t}\n\tif err := os.Chmod(path, 0o600); err != nil {\n\t\treturn nil, fmt.Errorf(\"native session key chmod: %w\", err)\n\t}\n\treturn key, nil\n}","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/proxy/internal/nativeruntime/marker.go#L31-L67","documentation":"The final Close() of the newly written session.key returned an error (e.g. delayed EIO from a failed flush). The function treats any close failure as fatal because the key's on-disk state is uncertain. This is the rarest failure in the write path and, like the other write-path errors, is paired with cleanup of the partial file where the handle is still open.","triggerScenarios":"NFS close flushing dirty pages that hit a server error; full disk surfacing at close; file handle invalidated by a forced unmount.","commonSituations":"Network home directories; storage disconnected while the process was starting.","solutions":["Check the underlying errno in the wrapped error — EIO on close usually means the write path is unhealthy","Verify the mount is healthy (remount NFS, check server) and retry","Relocate home to local disk if this recurs"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"key, err := nativeruntime.LoadOrCreateSessionKey(home)\nif err != nil && strings.Contains(err.Error(), \"session key close\") {\n    // close-time EIO: verify the file instead of trusting or discarding it blindly\n    if b, rerr := os.ReadFile(filepath.Join(home, \"runtime\", \"session.key\")); rerr == nil && len(b) == 32 {\n        key = b // key survived despite close error\n    }\n}","preventionTips":["Treat close errors on network mounts as storage-health signals","Remount/repair the volume, then restart — startup is idempotent","Keep home on reliable local storage"],"tags":["filesystem","io","nativeruntime","session-key"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}