dbt-labs/dbt-core · error

failed to write show result to stdout

Error message

failed to write show result to stdout

What it means

This panic comes from an `.expect()` on `Stdout::write_all` inside the TUI tracing layer's `handle_show_result`. It fires when dbt fails to write a `show` result (in quiet mode: raw content, no title header) to stdout. The most common underlying cause is a broken pipe — the downstream consumer (e.g. `head`, a pager, or a closed terminal) has stopped reading or the pipe is closed, so the write fails and the panic message surfaces instead of the data.

Solutions

  1. Avoid piping dbt output to commands that exit early (e.g. `head`); redirect to a file instead: `dbt show ... > out.txt`.
  2. Set RUST_BACKTRACE=1 and check the panic source; if it is broken-pipe, confirm the downstream reader consumes all output.
  3. Restore a valid stdout — run dbt in a live terminal or with stdout attached to a file, not a closed descriptor.
  4. If the process must survive closed pipes, invoke dbt with output to stderr only (quiet/suppress options) so the show-result write path is not hit.
  5. Upgrade dbt — newer versions may replace `.expect` with graceful SIGPIPE handling.

Example fix

// before
stdout
    .write_all(format!("{}\n", show_result.content).as_bytes())
    .expect("failed to write show result to stdout");
// after
let _ = stdout
    .write_all(format!("{}\n", show_result.content).as_bytes());
stdout.flush().ok();
Defensive patterns

Strategy: try-catch

Validate before calling

// bash: ensure stdout is writable and no early-exiting pipe consumer
[ -w /dev/stdout ] && echo "stdout writable"

Try / catch

// from the library side: replace expect with error-tolerant write
if let Err(e) = stdout.write_all(bytes) {
    eprintln!("show result not written: {e}");
}

Prevention

When it happens

Trigger: A dbt `show` invocation whose output is piped into a command that exits early (e.g. `dbt show ... | head -5`), or whose stdout is a closed/invalid file descriptor, causing `write_all` on the locked stdout to return Err and the `.expect` to panic.

Common situations: Developers piping `dbt show` output into `head`, `less -F`, or a script that exits before reading all output; running dbt in CI with stdout redirected to a closed stream; terminal emulators closing the PTY mid-run.

Related errors


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

Appendix: source

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

            let mut stdout = io::stdout().lock();

            stdout
                .write_all(format!("{}\n", show_data.content).as_bytes())
                .expect("failed to write show data to stdout");
        });
    }

    fn handle_show_result(&self, show_result: &ShowResult) {
        self.write_suspended(|| {
            let mut stdout = io::stdout().lock();

            if self.show_options.is_empty() {
                // Quiet mode: suppress decorative title, emit raw content only.
                // Mirrors dbt-core's ShowNode quiet=True behaviour where the
                // "Previewing node 'X':" header is dropped but the data is kept.
                stdout
                    .write_all(format!("{}\n", show_result.content).as_bytes())
                    .expect("failed to write show result to stdout");
            } else {
                let colored_title = BLUE.apply_to(&show_result.title);
                stdout
                    .write_all(format!("\n{}\n{}\n", colored_title, show_result.content).as_bytes())
                    .expect("failed to write show result to stdout");
            }
        });
    }

    fn handle_compiled_code_inline(&self, compiled_code: &CompiledCodeInline) {
        // Only show if any Progress*, Completed or All option is enabled
        let should_show = self.show_options.contains(&ShowOptions::Progress)
            || self.show_options.contains(&ShowOptions::ProgressRender)
            || self.show_options.contains(&ShowOptions::Completed)
            || self.show_options.contains(&ShowOptions::All);

        if !should_show {
            return;

View on GitHub (pinned to 0267ce9170)