swc-project/swc · error
failed to emit error: {e}
Error message
failed to emit error: {e} What it means
Runtime panic in swc_common's EmitterWriter (crates/swc_common/src/errors/emitter.rs). After a diagnostic's primary message is rendered into a StyledBuffer, `emit_to_destination` writes it to the destination stream (stderr/stdout/file/buffer); if that write returns an I/O error, the emitter panics with `failed to emit error: {e}` instead of continuing. Rust ignores SIGPIPE by default, so a closed pipe surfaces here as an EPIPE write error.
Source
Thrown at crates/swc_common/src/errors/emitter.rs:1367
} else {
self.get_max_line_num(span, children).to_string().len()
};
match self.emit_message_default(span, message, code, level, max_line_num_len, false) {
Ok(()) => {
if !children.is_empty() {
let mut buffer = StyledBuffer::new();
if !self.short_message {
draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1);
}
match emit_to_destination(
&buffer.render(),
level,
&mut self.dst,
self.short_message,
) {
Ok(()) => (),
Err(e) => panic!("failed to emit error: {e}"),
}
}
if !self.short_message {
for child in children {
let span = child.render_span.as_ref().unwrap_or(&child.span);
if let Err(e) = self.emit_message_default(
span,
child.styled_message(),
&None,
child.level,
max_line_num_len,
true,
) {
panic!("failed to emit error: {e}")
}
}
for sugg in suggestions {
if let Err(e) =View on GitHub (pinned to 5176682b65)
Solutions
- Avoid early-exiting readers in pipelines (buffer output, or read the full output before closing)
- Restore default SIGPIPE behavior so the process terminates cleanly instead of panicking: `unsafe { libc::signal(libc::SIGPIPE, libc::SIG_DFL) }`
- Give the Handler an emitter writing to a destination you control (in-memory buffer) and print it yourself with error handling
Example fix
// before
let handler = Handler::with_tty_emitter(true, false); // writes to stderr; panics on EPIPE
// after
let buffer = WritableDestination::buffer();
let handler = Handler::with_emitter(true, false, Box::new(EmitterWriter::new(buffer.clone())));
// ... after run: match buffer.try_into_inner() { Ok(s) => { let _ = write!(io::stderr(), "{s}"); }, Err(_) => {} } Defensive patterns
Strategy: try-catch
Try / catch
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
err.into_diagnostic(&handler).emit();
}));
if result.is_err() {
// destination write failed: fall back to a plain eprintln and continue
let _ = writeln!(io::stderr(), "warning: failed to render diagnostic");
} Prevention
- Do not pipe diagnostic-producing output to early-exiting readers like `head -1`
- Consider restoring default SIGPIPE disposition (`libc::signal(SIGPIPE, SIG_DFL)`) in CLI binaries
- Route diagnostics into an in-memory WritableDestination buffer and flush once with handled Result
When it happens
Trigger: Running swc with diagnostics piped to a short-lived reader (e.g. `swc ... | head -1`) that closes the pipe; stderr/stdout redirected to a closed fd or full disk; a custom Destination whose writer fails.
Common situations: CLI usage in shell pipelines where the downstream command exits early; CI log capture on a full disk; wasm/embedded hosts providing a broken writable destination.
Related errors
- illegal conversion: Cannot convert {:?} to PatOutput
- unable to access unknown nodes
- illegal conversion: Cannot convert {:?} to Pattern
- illegal conversion: Cannot convert {:?} to LVal
- illegal conversion: Cannot convert {:?} to AssignmentPattern
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/c9c04a87133469ce.
Report an issue: GitHub.