rust-lang/cargo · error
cannot open specified crate's documentation: no…
Error message
cannot open specified crate's documentation: no documentation generated
What it means
Thrown by `cargo doc --open` when the compilation produced zero root crate names, meaning there is no documentation file to open in a browser. `root_crate_names` is empty when no root-level crate (lib/bin) was documented — e.g. the package has no doc-able root target, all targets were filtered out, or only dependencies were compiled. Because `--open` needs a concrete path to launch, cargo refuses rather than guessing.
Solutions
- Drop `--open` when you only need docs generated without auto-launching: `cargo doc`.
- Select a real member that has a doc-able root crate: `cargo doc --open -p <member-with-lib>`.
- Ensure the target you want documented has `doc = true` (default) and is not excluded via `--exclude` or target-level `doc = false`.
- For virtual workspaces, run `cargo doc --open` from inside a member directory or pass an explicit `-p <member>`.
- If you scripted `--open`, guard it: only pass `--open` when at least one root crate is expected.
Example fix
# before $ cargo doc --open -p some-dependency # error: no documentation generated # after $ cargo doc -p some-dependency # just builds, no open $ cargo doc --open -p my-workspace-member # opens the member's docs
Defensive patterns
Strategy: validation
Validate before calling
// Before calling `cargo doc --open` programmatically, check that a root crate will be produced.
fn should_open(has_doc_root: bool, want_open: bool) -> bool { want_open && has_doc_root }
// Determine has_doc_root from `cargo metadata` (members with a lib/bin target where doc != false). Type guard
fn has_docable_root(targets: &[TargetInfo]) -> bool {
targets.iter().any(|t| (t.is_lib || t.is_bin) && t.doc_enabled)
} Prevention
- Only pass `--open` when you know a root crate will be documented (e.g. a member with a lib target).
- For scripted doc generation, omit `--open` and open the path yourself after confirming it exists.
- In virtual workspaces, always select a member with `-p` before `--open`.
- Avoid `--open` when documenting a dependency-only selection.
When it happens
Trigger: Running `cargo doc --open` (or `--open` with any output format) on a package/selection that yields no root crate to document: a package with only `[[bin]]` targets that are all excluded, a doc-build where `root_crate_names` came back empty (e.g. `cargo doc -p <dep-only-crate>` with no members), or `cargo doc --no-deps` on a virtual manifest workspace with no selected member.
Common situations: Running `cargo doc --open` from a workspace root with `-p` pointing at a dependency instead of a member. Pointing `--open` at a crate whose lib target has `doc = false`. A virtual workspace (`[workspace]` only, no `[package]`) with no package selector. After deleting `src/lib.rs` but keeping `--open` in a script.
Related errors
- can't specify both lib and binary outputs
- cannot create package in the home directory help: use…
- `cargo init` cannot be run on existing Cargo packages help…
- destination ` ` already exists Use `cargo init` to…
- metadata version not supported, only is currently supported
AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11).
Data as JSON: /api/errors/6dd2be052399d1fd.
Report an issue: GitHub.
Appendix: source
Thrown at src/ops/cargo_doc.rs:68
pub open_result: bool,
/// Same as `rustdoc --output-format`
pub output_format: OutputFormat,
/// Options to pass through to the compiler
pub compile_opts: ops::CompileOptions,
}
/// Main method for `cargo doc`.
pub fn doc(ws: &Workspace<'_>, options: &DocOptions) -> CargoResult<()> {
let compilation = ops::compile(ws, &options.compile_opts)?;
let wants_json_doc = matches!(options.output_format, OutputFormat::Json);
if ws.gctx().cli_unstable().rustdoc_mergeable_info && !wants_json_doc {
merge_cross_crate_info(ws, &compilation)?;
}
if options.open_result {
let name = &compilation.root_crate_names.get(0).ok_or_else(|| {
anyhow::anyhow!(
"cannot open specified crate's documentation: no documentation generated"
)
})?;
let kind = options.compile_opts.build_config.single_requested_kind()?;
let path = path_by_output_format(&compilation, &kind, &name, &options.output_format);
if path.exists() {
util::open::open(&path, ws.gctx())?;
}
} else if ws.gctx().shell().verbosity() == Verbosity::Verbose {
for name in &compilation.root_crate_names {
for kind in &options.compile_opts.build_config.requested_kinds {
let path =
path_by_output_format(&compilation, &kind, &name, &options.output_format);
if path.exists() {
let mut shell = ws.gctx().shell();
let link = shell.err_file_hyperlink(&path);View on GitHub (pinned to eb98b54bc9)