{"record":{"id":"db2654cce63494a0","repo":"wavetermdev/waveterm","slug":"failed-to-open-dev-null-w","errorCode":null,"errorMessage":"failed to open /dev/null: %w","messagePattern":"failed to open /dev/null: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/jobmanager/jobmanager_unix.go","lineNumber":28,"sourceCode":"\t\"log\"\n\t\"os\"\n\t\"os/signal\"\n\t\"path/filepath\"\n\t\"syscall\"\n\n\t\"github.com/wavetermdev/waveterm/pkg/wavebase\"\n\t\"golang.org/x/sys/unix\"\n)\n\nfunc daemonize(clientId string, jobId string) error {\n\t_, err := unix.Setsid()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to setsid: %w\", err)\n\t}\n\n\tdevNull, err := os.OpenFile(\"/dev/null\", os.O_RDWR, 0)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open /dev/null: %w\", err)\n\t}\n\terr = unix.Dup2(int(devNull.Fd()), int(os.Stdin.Fd()))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to dup2 stdin: %w\", err)\n\t}\n\tdevNull.Close()\n\n\tlogPath := wavebase.GetRemoteJobFilePath(jobId, \"log\")\n\tlogDir := filepath.Dir(logPath)\n\terr = os.MkdirAll(logDir, 0700)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to create log directory: %w\", err)\n\t}\n\n\tlogFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open log file: %w\", err)\n\t}","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/jobmanager/jobmanager_unix.go#L10-L46","documentation":"After Setsid, daemonize opens /dev/null read-write and duplicates it over stdin to detach the daemon from the controlling terminal. This error wraps the os.OpenFile(\"/dev/null\", O_RDWR, 0) failure. On Linux /dev/null is always present, so failures indicate an unusual or broken filesystem/device environment.","triggerScenarios":"os.OpenFile(\"/dev/null\", os.O_RDWR, 0) fails: /dev/null missing or is not a character device, /dev not mounted (chroot/minimal container), or permission denied on the device node.","commonSituations":"Minimal containers or chroots without /dev mounted; /dev/null accidentally deleted or replaced by a regular file with wrong perms; extremely low fd/file permissions after privilege drop; broken device nodes in exotic sandbox environments.","solutions":["Verify /dev/null exists and is a character device: ls -l /dev/null (expect crw-rw-rw-)","Recreate it if broken: mknod /dev/null c 1 3 && chmod 666 /dev/null","Mount /dev (or run with proper device cgroup allowances) in containers/chroots","Check that the process's uid can open the node read-write before daemonizing"],"exampleFix":"// before\ndevNull, err := os.OpenFile(\"/dev/null\", os.O_RDWR, 0)\nif err != nil {\n    return fmt.Errorf(\"failed to open /dev/null: %w\", err)\n}\n// after\ndevNull, err := os.OpenFile(\"/dev/null\", os.O_RDWR, 0)\nif err != nil {\n    if fi, serr := os.Stat(\"/dev/null\"); serr != nil || !fi.Mode().IsRegular() == false {\n        return fmt.Errorf(\"/dev/null is not a proper device, fix container /dev: %w\", err)\n    }\n    return fmt.Errorf(\"failed to open /dev/null: %w\", err)\n}","handlingStrategy":"validation","validationCode":"if fi, err := os.Stat(\"/dev/null\"); err != nil {\n    return fmt.Errorf(\"/dev/null missing: mount /dev\")\n} else if fi.Mode()&os.ModeCharDevice == 0 {\n    return fmt.Errorf(\"/dev/null is not a character device\")\n}","typeGuard":null,"tryCatchPattern":"if err := daemonize(clientId, jobId); err != nil {\n    if strings.Contains(err.Error(), \"failed to open /dev/null\") {\n        log.Printf(\"container/chroot /dev broken: %v\", errors.Unwrap(err))\n    }\n    return err\n}","preventionTips":["Ensure /dev is mounted with a proper /dev/null node in containers and chroots","Recreate a broken /dev/null with mknod c 1 3 and mode 666","Verify device cgroup / sandbox policies allow opening /dev/null","Pre-flight stat /dev/null when deploying to minimal images"],"tags":["go","unix","daemonize","devnull","filesystem"],"backgroundTag":"devnull-open-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}