dbt-labs/dbt-core · error

failed to write to stderr

Error message

failed to write to stderr

What it means

The invocation-end summary writes an "Errors and Warnings" header and each message to stderr with .expect("failed to write to stderr"). A stderr write failure (closed stream, broken pipe, full disk) panics.

Source

Thrown at crates/dbt-common/src/tracing/layers/tui_layer.rs:761

                        .expect("failed to write to stdout");
                }
            }

            // Print errors and warnings with header if any exist (on stderr)
            if !delayed_messages.errors_and_warnings.is_empty() {
                stderr
                    .write_all(
                        format!(
                            "\n{}\n",
                            format_delimiter(
                                " Errors and Warnings ",
                                self.max_term_line_width,
                                true
                            )
                        )
                        .as_bytes(),
                    )
                    .expect("failed to write to stderr");

                for msg in &delayed_messages.errors_and_warnings {
                    stderr
                        .write_all(msg.message.as_bytes())
                        .expect("failed to write to stderr");
                }
            }

            // Flush streams if we had any messages
            if !delayed_messages.test_failures.is_empty()
                || !delayed_messages.errors_and_warnings.is_empty()
            {
                stderr.flush().expect("failed to write to stderr");
                stdout.flush().expect("failed to write to stdout");
            }
        });

        // Then print the invocation summary

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Ensure stderr is attached to a live sink (tty, file) for the whole run
  2. Avoid pipelines that close early on combined output; capture stderr to a file instead
  3. Handle the io::Error in code (skip BrokenPipe) instead of .expect

Example fix

// before
stderr.write_all(msg.message.as_bytes()).expect("failed to write to stderr");
// after
if let Err(e) = stderr.write_all(msg.message.as_bytes()) {
    if e.kind() != io::ErrorKind::BrokenPipe {
        eprintln!("failed to write to stderr: {e}");
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// shell: test -w /dev/stderr && echo "stderr writable"

Try / catch

if let Err(e) = stderr.write_all(bytes) {
    if e.kind() != io::ErrorKind::BrokenPipe { eprintln!("stderr write failed: {e}"); }
}

Prevention

When it happens

Trigger: handle_invocation_end sees non-empty delayed_messages.errors_and_warnings and writing the header or a message to stderr fails — e.g. `dbt 2>&1 | head`, detached terminal, or stderr redirected to an unwritable/full target.

Common situations: Capturing only stdout while the stderr consumer exited; combined `2>&1 | head` pipelines; containers whose stderr pipe was closed by the orchestrator.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/9c3ff17c755dc280. Report an issue: GitHub.