{"record":{"id":"37345b95cdfa4cde","repo":"slimtoolkit/slim","slug":"cannot-open-file-q-to-duplicate-app-s-s-stream","errorCode":null,"errorMessage":"cannot open file %q to duplicate app's %s stream: %w","messagePattern":"cannot open file %q to duplicate app's (.+?) stream: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/app/sensor/monitor/composite.go","lineNumber":356,"sourceCode":"\t\tPtReport:  ptReport,\n\t}, nil\n}\n\nfunc NonCriticalError(err error) error {\n\treturn fmt.Errorf(\"non-critical monitor error: %w\", err)\n}\n\n// Using simple io.MultiWriter(os.Stdout, os.File) would make cmd.Wait()\n// block until either the cmd's stdout is closed or the multi-writer is closed.\n// However, both are impossible. We need the Wait() to return much earlier\n// than the process termination (see pkg/monitors/ptrace logic), and multi-writer\n// cannot be closed at all. Hence, the pipe trick.\nfunc dupAppStdStream(artifactsDir string, w io.Writer, kind string) (*os.File, *os.File, error) {\n\tfilename := filepath.Join(artifactsDir, \"app_\"+kind+\".log\")\n\n\tf, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0o644)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"cannot open file %q to duplicate app's %s stream: %w\", filename, kind, err)\n\t}\n\n\tpr, pw, err := os.Pipe()\n\tif err != nil {\n\t\tf.Close()\n\t\treturn nil, nil, fmt.Errorf(\"cannot create pipe for app %s stream: %w\", kind, err)\n\t}\n\n\tgo func() {\n\t\tn, err := io.Copy(io.MultiWriter(w, f), pr)\n\t\tlog.Debugf(\"dupAppStdStream: io.Copy() finished; written=%d error=%v\", n, err)\n\t}()\n\n\treturn pw, f, nil\n}\n\nfunc closeAll(cs []io.Closer) {\n\tfor _, c := range cs {","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/slimtoolkit/slim/blob/81940d17fa112cc678e32209214bcb2355cb3004/pkg/app/sensor/monitor/composite.go#L338-L374","documentation":"dupAppStdStream creates a log file in artifactsDir (app_<stdout|stderr>.log) to which the app's stream is duplicated. This error is returned when os.OpenFile fails to create/open that file, wrapping the underlying OS error.","triggerScenarios":"Calling NewCompositeMonitor when the artifacts directory does not exist, is not writable by the current user, is on a full/read-only filesystem, or the filename is invalid.","commonSituations":"artifactsDir pointing to a non-existent path or one created with restrictive permissions; running the sensor as a non-root user without write access; disk full; read-only container filesystem.","solutions":["Ensure the artifacts directory exists and is writable by the user running the sensor (mkdir -p and chown/chmod as needed).","Check the wrapped OS error for specifics (ENOENT, EACCES, ENOSPC) and fix accordingly.","Verify there is free disk space and the filesystem is not mounted read-only."],"exampleFix":"// before\nNewCompositeMonitor(cfg{ArtifactsDir: \"/nonexistent/dir\"})\n// after\nos.MkdirAll(\"/var/log/artifacts\", 0o755)\nNewCompositeMonitor(cfg{ArtifactsDir: \"/var/log/artifacts\"})","handlingStrategy":"validation","validationCode":"if info, err := os.Stat(artifactsDir); err != nil || !info.IsDir() {\n    return fmt.Errorf(\"artifacts dir %q missing\", artifactsDir)\n}\nprobe, err := os.OpenFile(filepath.Join(artifactsDir, \".write_probe\"), os.O_CREATE|os.O_WRONLY, 0o644)\nif err != nil {\n    return fmt.Errorf(\"artifacts dir not writable: %w\", err)\n}\nprobe.Close()","typeGuard":null,"tryCatchPattern":"mon, err := NewCompositeMonitor(cfg)\nif err != nil {\n    if strings.Contains(err.Error(), \"cannot open file\") {\n        return fmt.Errorf(\"check artifacts dir permissions/disk space: %w\", err)\n    }\n    return err\n}","preventionTips":["Create the artifacts directory with os.MkdirAll and permissive-enough mode before starting monitors.","Run the sensor with a user that owns or can write the artifacts directory.","Monitor free disk space on the artifacts volume."],"tags":["filesystem","permissions","logging"],"backgroundTag":"permission-denied","analyzedSha":"81940d17fa112cc678e32209214bcb2355cb3004","analyzedAt":"2026-08-31T23:06:12.682Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}