dbt-labs/dbt-core · error

failed to write show data to stdout

Error message

failed to write show data to stdout

What it means

handle_show_data_output writes show-query content to a locked stdout with .expect('failed to write show data to stdout'), panicking on write failure. The `dbt show` results must reach the terminal, so the layer treats write failure as fatal. The write fails when stdout's consumer has vanished or the target is unwritable.

Solutions

  1. Pipe into tee to a file rather than commands that exit early
  2. Check disk space/quota on the redirect target
  3. Keep the capturing harness alive until dbt exits
  4. Make the write non-fatal (warn and continue) instead of .expect

Example fix

// before
.expect("failed to write show data to stdout");
// after
if let Err(e) = stdout.write_all(format!("{}\n", show_data.content).as_bytes()) {
    eprintln!("warning: could not write show data: {e}");
}
Defensive patterns

Strategy: try-catch

Validate before calling

# preflight disk space and descriptor before show
df -h . && dbt show --inline 'select 1' > show_out.txt 2>&1

Type guard

fn stdout_writable() -> bool {
    use std::io::Write;
    io::stdout().flush().is_ok()
}

Try / catch

// detect failure and fall back to file output
dbt show --inline 'select 1' 2>err.log || { grep -q 'failed to write show data to stdout' err.log && dbt show --inline 'select 1' > out.txt; }

Prevention

When it happens

Trigger: A ShowDataOutput record arrives via on_log_record and write_all fails: pipe reader exited, pty closed, or redirected file cannot accept data (ENOSPC).

Common situations: `dbt show ... | head` truncating consumers; running under a wrapper that closed stdout; disk-quota errors when redirecting show output.

Related errors


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

Appendix: source

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

                        .write_all(format!("{}\n", header).as_bytes())
                        .expect("failed to write header to stdout");
                }

                // Print list item content (always — result payload survives quiet)
                stdout
                    .write_all(format!("{}\n", list_item.content).as_bytes())
                    .expect("failed to write to stdout");
            });
        }
    }

    fn handle_show_data_output(&self, show_data: &ShowDataOutput) {
        self.write_suspended(|| {
            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())

View on GitHub (pinned to 0267ce9170)