{"record":{"id":"4d5d828659aec405","repo":"dagger/dagger","slug":"write-logs-w","errorCode":null,"errorMessage":"write logs: %w","messagePattern":"write logs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cmd/dagger/analyze_cloud.go","lineNumber":124,"sourceCode":"\t\t\t// (and anything grepping it) sees the original stream. Empty\n\t\t\t// bodies are stream markers (EOF, progress); skip them so they\n\t\t\t// don't inflate the message count.\n\t\t\tif m.Body == \"\" {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tn++\n\t\t\tif _, err := io.WriteString(w, m.Body); err != nil {\n\t\t\t\t// Nothing more can be written (disk full, closed pipe);\n\t\t\t\t// stop the stream rather than silently dropping the rest.\n\t\t\t\twriteErr = err\n\t\t\t\tcancel()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tendedWithNewline = strings.HasSuffix(m.Body, \"\\n\")\n\t\t}\n\t})\n\tif writeErr != nil {\n\t\treturn fmt.Errorf(\"write logs: %w\", writeErr)\n\t}\n\t// A deadline is an expected way to stop a long stream, not an error.\n\tif streamErr != nil && !errors.Is(ctx.Err(), context.DeadlineExceeded) {\n\t\treturn streamErr\n\t}\n\tif !endedWithNewline {\n\t\t// End on a newline without having invented line breaks mid-stream.\n\t\tio.WriteString(w, \"\\n\")\n\t}\n\tif outFile != nil {\n\t\t// Surface close errors (e.g. a deferred flush failing on a full disk)\n\t\t// instead of reporting success over a truncated file.\n\t\tif err := outFile.Close(); err != nil {\n\t\t\treturn fmt.Errorf(\"close %s: %w\", logsOutput, err)\n\t\t}\n\t\tfmt.Fprintf(cmd.ErrOrStderr(), \"wrote %d log messages to %s\\n\", n, logsOutput)\n\t}\n\treturn nil","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/internal/cmd/dagger/analyze_cloud.go#L106-L142","documentation":"In the CloudLogs command, the StreamLogs handler writes each log message body verbatim to the output writer; if a Write fails (disk full, closed pipe), the handler records writeErr and cancels the stream, and the command then returns this wrapped error instead of silently dropping output.","triggerScenarios":"`dagger cloud logs` (with or without --output file) writing to stdout when the downstream reader exits (e.g. `| head`), or writing to a file on a full filesystem or read-only mount.","commonSituations":"Piping into head/less that closes early → EPIPE; disk quota exceeded while writing --output logs.log; container with full tmpfs.","solutions":["Free disk space or write to a location with room","Avoid pipes that close early, or accept truncation (`|| true`)","Check the wrapped writeErr for the specific OS error (ENOSPC, EPIPE)","If piping intentionally, redirect to a file instead"],"exampleFix":"// before\ndagger cloud logs --trace X | head -n 10   # EPIPE\n// after\ndagger cloud logs --trace X --output logs.txt && head -n 10 logs.txt","handlingStrategy":"validation","validationCode":"if outPath != \"\" {\n\tif st, err := os.Stat(filepath.Dir(outPath)); err != nil || !st.IsDir() {\n\t\treturn fmt.Errorf(\"output dir %s unavailable\", filepath.Dir(outPath))\n\t}\n\tif free, err := diskFree(filepath.Dir(outPath)); err == nil && free < 100<<20 {\n\t\treturn fmt.Errorf(\"less than 100MB free on %s\", filepath.Dir(outPath))\n\t}\n}","typeGuard":null,"tryCatchPattern":"// pre-check before streaming to a pipe\nout, err := os.Stdout.Stat()\nif err == nil && (out.Mode()&os.ModeNamedPipe) != 0 {\n\t// writing to a pipe; downstream may close early — handle SIGPIPE/EPIPE\n}","preventionTips":["Write logs to a file (--output) instead of fragile pipes","Ensure adequate disk space before long log dumps","Avoid piping into commands that exit early (head) or trap SIGPIPE","Check wrapped OS error (ENOSPC vs EPIPE) to pick the right fix"],"tags":["io","write","disk-full","cli"],"backgroundTag":"write-failed-epipe","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}