rust-lang/mdBook · error
Command string was empty
Error message
Command string was empty
What it means
mdbook's compose_command builds a std::process::Command for an external renderer or preprocessor by shell-splitting the command string with Shlex. If the configured command string is empty (or contains only whitespace), there is no executable to run, so the library bails with this error instead of spawning an invalid process. It is a configuration validation error surfaced as a Result::Err.
Source
Thrown at crates/mdbook-driver/src/lib.rs:86
pub mod builtin_renderers;
pub mod init;
mod load;
mod mdbook;
use anyhow::{Context, Result, bail};
pub use mdbook::MDBook;
pub use mdbook_core::{book, config, errors};
use shlex::Shlex;
use std::path::{Path, PathBuf};
use std::process::Command;
use tracing::{error, warn};
/// Creates a [`Command`] for command renderers and preprocessors.
fn compose_command(cmd: &str, root: &Path) -> Result<Command> {
let mut words = Shlex::new(cmd);
let exe = match words.next() {
Some(e) => PathBuf::from(e),
None => bail!("Command string was empty"),
};
let exe = if exe.components().count() == 1 {
// Search PATH for the executable.
exe
} else {
// Relative path is relative to book root.
root.join(&exe)
};
let mut cmd = Command::new(exe);
for arg in words {
cmd.arg(arg);
}
Ok(cmd)
}View on GitHub (pinned to dc21064fc2)
Solutions
- Set a non-empty command for the renderer/preprocessor in book.toml, e.g. command = "mdbook-foo".
- If the command comes from an environment variable, ensure the variable is exported with the actual executable path before running mdbook.
- Remove the empty command key entirely so mdbook uses its default lookup for the preprocessor/renderer.
- If writing a plugin, validate the command string is non-empty (Shlex-parses to at least one token) before registering.
Example fix
// before (book.toml) [preprocessor.links] command = "" // after (book.toml) [preprocessor.links] command = "mdbook-links"
Defensive patterns
Strategy: validation
Validate before calling
let cmd = config.get("output.my-renderer.command").unwrap_or("");
if cmd.trim().is_empty() {
return Err(anyhow!("renderer command must be a non-empty string"));
} Type guard
fn has_command(cmd: &Option<String>) -> bool {
cmd.as_deref().map(|c| !c.trim().is_empty()).unwrap_or(false)
} Prevention
- Always set an explicit non-empty command for custom renderers/preprocessors.
- Check environment-variable interpolation in book.toml resolves to a non-empty value.
- Run `mdbook build` in CI to catch config regressions early.
When it happens
Trigger: Setting a renderer or preprocessor command in book.toml to an empty string (e.g. `output.xyz.command = ""` or `[preprocessor.foo]\ncommand = ""`), or passing an empty/whitespace-only cmd to any code path that calls compose_command.
Common situations: Empty command inherited from an environment variable interpolation (e.g. MY_CMD="" mdbook build), a config templating step that dropped the value, or hand-edited book.toml where the command value was accidentally deleted but the key kept.
Related errors
AI-assisted analysis of rust-lang/mdBook@dc21064fc2 (2026-09-01).
Data as JSON: /api/errors/3a125f4bcb57625c.
Report an issue: GitHub.