rust-lang/cargo · error

can't find library ` `, rename file to `src/lib.rs` or…

Error message

can't find library `{name}`, rename file to `src/lib.rs` or specify lib.path

What it means

When resolving a `[lib]` target, Cargo tries to infer the source file: first `src/lib.rs`, then (edition 2015 only) `src/<name>.rs` with a deprecation warning. If `lib.path` is unset and none of those files exist on disk (`package_root.join(...).exists()` is false), the parser cannot proceed and bails. The library target must point at a real file.

Solutions

  1. Create `src/lib.rs` (the conventional default).
  2. Set `[lib] path = "src/your_name.rs"` to point at the actual file.
  3. Remove the `[lib]` table entirely if the crate is not a library.

Example fix

# before
[lib]
# no path set; src/lib.rs missing

# after
[lib]
path = "src/my_lib.rs"
Defensive patterns

Strategy: validation

Validate before calling

use std::path::Path;
fn lib_path_resolves(pkg_root: &Path, lib_path: Option<&str>, name: &str, ed2015: bool) -> bool {
    if let Some(p) = lib_path { return pkg_root.join(p).exists(); }
    if pkg_root.join("src/lib.rs").exists() { return true; }
    ed2015 && pkg_root.join("src").join(format!("{name}.rs")).exists()
}
// call before `cargo build` to fail fast with a clear message

Prevention

When it happens

Trigger: A `[lib]` section (or a package whose name implies a lib) is present, `lib.path` is unset, there is no `src/lib.rs`, and either the edition is 2018+ or `src/<name>.rs` also does not exist. The `else` branch at targets.rs:201-205 fires.

Common situations: Renaming `src/lib.rs` to a custom path without updating `lib.path`. Splitting a binary-only crate that still has a leftover `[lib]` table. Cloning a repo where the library source lives under `src/` but with a non-default name on edition 2018+.

Related errors


AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11). Data as JSON: /api/errors/d0d80827e7cd70e8. Report an issue: GitHub.

Appendix: source

Thrown at src/workspace/parser/targets.rs:202

        validate_proc_macro(&lib, TARGET_KIND_HUMAN_LIB, edition, warnings)?;
        validate_crate_types(&lib, TARGET_KIND_HUMAN_LIB, edition, warnings)?;

        if lib.path.is_none() {
            if let Some(inferred) = inferred {
                lib.path = Some(PathValue(inferred));
            } else {
                let name = name_or_panic(&lib);
                let legacy_path = Path::new("src").join(format!("{name}.rs"));
                if edition == Edition::Edition2015 && package_root.join(&legacy_path).exists() {
                    warnings.push(format!(
                        "path `{}` was erroneously implicitly accepted for library `{name}`,\n\
                     please rename the file to `src/lib.rs` or set lib.path in Cargo.toml",
                        legacy_path.display(),
                    ));
                    lib.path = Some(PathValue(legacy_path));
                } else {
                    anyhow::bail!(
                        "can't find library `{name}`, \
                     rename file to `src/lib.rs` or specify lib.path",
                    )
                }
            }
        }

        if let Some(PathValue(path)) = lib.path.as_ref() {
            lib.path = Some(PathValue(paths::normalize_path(&path).into()));
        }

        Ok(Some(lib))
    }
}

#[tracing::instrument(skip_all)]
fn to_lib_target(
    original_lib: Option<&TomlLibTarget>,

View on GitHub (pinned to eb98b54bc9)