{"record":{"id":"53a370aafb271331","repo":"wavetermdev/waveterm","slug":"failed-to-create-log-directory-w","errorCode":null,"errorMessage":"failed to create log directory: %w","messagePattern":"failed to create log directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/jobmanager/jobmanager_unix.go","lineNumber":40,"sourceCode":"\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}\n\terr = unix.Dup2(int(logFile.Fd()), int(os.Stdout.Fd()))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to dup2 stdout: %w\", err)\n\t}\n\terr = unix.Dup2(int(logFile.Fd()), int(os.Stderr.Fd()))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to dup2 stderr: %w\", err)\n\t}\n\n\tlog.SetOutput(logFile)\n\tlog.Printf(\"job manager daemonized, logging to %s\\n\", logPath)\n\tlog.Printf(\"job owner clientid: %s\\n\", clientId)","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/jobmanager/jobmanager_unix.go#L22-L58","documentation":"daemonize creates the directory for the job log file (wavebase.GetRemoteJobFilePath(jobId, \"log\")) with os.MkdirAll(0700) before opening it. This error wraps that MkdirAll failure. It means the job-control directory under the Wave home/sessions tree could not be created, typically a permissions or disk problem.","triggerScenarios":"os.MkdirAll(logDir, 0700) fails because the Wave data directory is unwritable, a path component exists as a regular file, the disk is full, or the home directory is read-only/not mounted.","commonSituations":"Read-only home directory or NFS mount without write access; WAVE_HOME/env override pointing at an unwritable path; leftover file where a directory is expected; ENOSPC on the data volume; SELinux denials on the home tree.","solutions":["Check the wrapped errno and verify the log directory path is writable by the current uid","Confirm the Wave data directory (and any configured override) exists and is not read-only","Free disk space if the error is ENOSPC","Remove any regular file occupying the logDir path so MkdirAll can create the directory"],"exampleFix":"// before\nerr = os.MkdirAll(logDir, 0700)\nif err != nil {\n    return fmt.Errorf(\"failed to create log directory: %w\", err)\n}\n// after\nif err := os.MkdirAll(logDir, 0700); err != nil {\n    if fi, serr := os.Lstat(logDir); serr == nil && !fi.IsDir() {\n        if rmErr := os.Remove(logDir); rmErr != nil {\n            return fmt.Errorf(\"log dir path blocked by file: %w\", rmErr)\n        }\n        err = os.MkdirAll(logDir, 0700)\n    }\n    if err != nil {\n        return fmt.Errorf(\"failed to create log directory %s: %w\", logDir, err)\n    }\n}","handlingStrategy":"try-catch","validationCode":"logPath := wavebase.GetRemoteJobFilePath(jobId, \"log\")\nlogDir := filepath.Dir(logPath)\nif fi, err := os.Lstat(logDir); err == nil && !fi.IsDir() {\n    return fmt.Errorf(\"%s exists and is not a directory\", logDir)\n}","typeGuard":null,"tryCatchPattern":"if err := daemonize(clientId, jobId); err != nil {\n    if strings.Contains(err.Error(), \"failed to create log directory\") {\n        log.Printf(\"log dir error: %v\", errors.Unwrap(err))\n        // check home/data dir writability, ENOSPC, blocking file\n    }\n    return err\n}","preventionTips":["Verify the Wave data/home directory is writable by the job uid","Check disk space and quotas on the data volume","Remove stray regular files occupying expected directory paths","Validate any env override controlling the data root points to a writable location"],"tags":["go","filesystem","permissions","logging","daemonize"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}