dagger/dagger · error

write logs: %w

Error message

write logs: %w

What it means

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.

Source

Thrown at internal/cmd/dagger/analyze_cloud.go:124

			// (and anything grepping it) sees the original stream. Empty
			// bodies are stream markers (EOF, progress); skip them so they
			// don't inflate the message count.
			if m.Body == "" {
				continue
			}
			n++
			if _, err := io.WriteString(w, m.Body); err != nil {
				// Nothing more can be written (disk full, closed pipe);
				// stop the stream rather than silently dropping the rest.
				writeErr = err
				cancel()
				return
			}
			endedWithNewline = strings.HasSuffix(m.Body, "\n")
		}
	})
	if writeErr != nil {
		return fmt.Errorf("write logs: %w", writeErr)
	}
	// A deadline is an expected way to stop a long stream, not an error.
	if streamErr != nil && !errors.Is(ctx.Err(), context.DeadlineExceeded) {
		return streamErr
	}
	if !endedWithNewline {
		// End on a newline without having invented line breaks mid-stream.
		io.WriteString(w, "\n")
	}
	if outFile != nil {
		// Surface close errors (e.g. a deferred flush failing on a full disk)
		// instead of reporting success over a truncated file.
		if err := outFile.Close(); err != nil {
			return fmt.Errorf("close %s: %w", logsOutput, err)
		}
		fmt.Fprintf(cmd.ErrOrStderr(), "wrote %d log messages to %s\n", n, logsOutput)
	}
	return nil

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Free disk space or write to a location with room
  2. Avoid pipes that close early, or accept truncation (`|| true`)
  3. Check the wrapped writeErr for the specific OS error (ENOSPC, EPIPE)
  4. If piping intentionally, redirect to a file instead

Example fix

// before
dagger cloud logs --trace X | head -n 10   # EPIPE
// after
dagger cloud logs --trace X --output logs.txt && head -n 10 logs.txt
Defensive patterns

Strategy: validation

Validate before calling

if outPath != "" {
	if st, err := os.Stat(filepath.Dir(outPath)); err != nil || !st.IsDir() {
		return fmt.Errorf("output dir %s unavailable", filepath.Dir(outPath))
	}
	if free, err := diskFree(filepath.Dir(outPath)); err == nil && free < 100<<20 {
		return fmt.Errorf("less than 100MB free on %s", filepath.Dir(outPath))
	}
}

Try / catch

// pre-check before streaming to a pipe
out, err := os.Stdout.Stat()
if err == nil && (out.Mode()&os.ModeNamedPipe) != 0 {
	// writing to a pipe; downstream may close early — handle SIGPIPE/EPIPE
}

Prevention

When it happens

Trigger: `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.

Common situations: Piping into head/less that closes early → EPIPE; disk quota exceeded while writing --output logs.log; container with full tmpfs.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/4d5d828659aec405. Report an issue: GitHub.