rust-lang/mdBook · error
The " " preprocessor exited unsuccessfully with status
Error message
The "{}" preprocessor exited unsuccessfully with {} status What it means
mdbook-driver runs a builtin preprocessor as a child process and calls `ensure!(output.status.success(), ...)` after waiting for it. When the child exits with a non-zero status, the ensure condition fails and this anyhow error is returned, embedding the preprocessor name and the exit status. It is the generic 'backend preprocessor crashed' error.
Solutions
- Run the preprocessor command standalone on a sample input to see its real error output.
- Check book.toml [preprocessor.X] command for typos and correct working directory assumptions.
- Fix the preprocessor so it exits 0 on success; make sure it reads/writes the (input, output) JSON files correctly.
- Run `mdbook build` with `RUST_LOG=trace` to see the child's captured output (traced just before the ensure).
Example fix
# before
defective_preproc.py # raises on error -> exit 1
# after
defective_preproc.py || { echo "preproc failed" >&2; cat debug-log; } # debug, then fix script to exit 0 on success Defensive patterns
Strategy: try-catch
Try / catch
match mdbook_driver::process(book).build(...) {
Err(e) if e.to_string().contains("exited unsuccessfully") => {
eprintln!("preprocessor failed: {e:#}"); // inspect the named preprocessor
}
Err(e) => eprintln!("build failed: {e:#}"),
Ok(_) => {}
} Prevention
- Test each preprocessor command standalone before wiring it into book.toml.
- Make preprocessors exit 0 on success and log errors to stderr.
- Pin/verify preprocessor binaries exist on PATH in CI.
- Run builds with RUST_LOG=trace to capture preprocessor output.
When it happens
Trigger: Any preprocessor command defined in book.toml ([preprocessor.<name>].command) exits with non-zero status during mdbook build/test/serve; e.g. the command binary is a failing script, or `mdbook build` runs `links`/`index` builtin preprocessors that return an error code.
Common situations: A custom preprocessor script exits 1 on bad markdown; preprocessor binary missing dependencies and aborting; preprocessor killed by signal (status shows signal, e.g. 'signal: 9'); typo'd command that runs but fails.
Related errors
- Duplicate file in SUMMARY.md
- failed to parse SUMMARY.md line
- internal error: expected empty tag stack. path
- no address found for
- [output.html.search.chapter] key
AI-assisted analysis of rust-lang/mdBook@dc21064fc2 (2026-09-01).
Data as JSON: /api/errors/59363112ce2fb0bc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/mdbook-driver/src/builtin_preprocessors/cmd.rs:99
)?;
// This should normally not be reached, since the validation
// for NotFound should have already happened when running the
// "supports" command.
return Ok(book);
}
};
self.write_input_to_child(&mut child, &book, ctx);
let output = child.wait_with_output().with_context(|| {
format!(
"Error waiting for the \"{}\" preprocessor to complete",
self.name
)
})?;
trace!("{} exited with output: {:?}", self.cmd, output);
ensure!(
output.status.success(),
format!(
"The \"{}\" preprocessor exited unsuccessfully with {} status",
self.name, output.status
)
);
serde_json::from_slice(&output.stdout).with_context(|| {
format!(
"Unable to parse the preprocessed book from \"{}\" processor",
self.name
)
})
}
fn supports_renderer(&self, renderer: &str) -> Result<bool> {
debug!(
"Checking if the \"{}\" preprocessor supports \"{}\"",View on GitHub (pinned to dc21064fc2)