rust-lang/cargo · error · anyhow::Error

single file packages cannot be used as dependencies

Error message

single file packages cannot be used as dependencies

What it means

Raised in `SourceId::load` (src/workspace/source_id.rs:401) for a `SourceKind::Path` dependency whose resolved path is a single file (passes `is_embedded(&path) && path.is_file()`). Cargo's path dependencies must be a directory containing a `Cargo.toml`; a lone `.rs` file is only valid as an embedded/crate-root inside a package, never as an external dependency source.

Source

Thrown at src/workspace/source_id.rs:402

    /// Returns `true` if this source from a Git repository.
    pub fn is_git(self) -> bool {
        matches!(self.inner.kind, SourceKind::Git(_))
    }

    /// Creates an implementation of `Source` corresponding to this ID.
    pub fn load<'a>(self, gctx: &'a GlobalContext) -> CargoResult<Box<dyn Source + 'a>> {
        trace!("loading SourceId; {}", self);
        match self.inner.kind {
            SourceKind::Git(..) => Ok(Box::new(GitSource::new(self, gctx)?)),
            SourceKind::Path => {
                let path = self
                    .inner
                    .url
                    .to_file_path()
                    .expect("path sources cannot be remote");
                if crate::workspace::parser::is_embedded(&path) && path.is_file() {
                    anyhow::bail!("single file packages cannot be used as dependencies")
                }
                Ok(Box::new(PathSource::new(&path, self, gctx)))
            }
            SourceKind::Registry | SourceKind::SparseRegistry => {
                Ok(Box::new(RegistrySource::remote(self, gctx)?))
            }
            SourceKind::LocalRegistry => {
                let path = self
                    .inner
                    .url
                    .to_file_path()
                    .expect("path sources cannot be remote");
                Ok(Box::new(RegistrySource::local(self, &path, gctx)))
            }
            SourceKind::Directory => {
                let path = self
                    .inner
                    .url

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Point the `path` at the directory containing the dependency's `Cargo.toml` (e.g. `path = "../my-lib"`).
  2. If you genuinely have a single-file crate, wrap it in a minimal package directory with its own `Cargo.toml`.
  3. Re-check the path is not accidentally resolving to a file via a glob or trailing filename.

Example fix

# before
[dependencies]
my-lib = { path = "./src/my_lib.rs" }
# after
[dependencies]
my-lib = { path = "./my-lib" }   # directory containing Cargo.toml
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_path_dep(p: &std::path::Path) -> bool {
    p.is_dir() && p.join("Cargo.toml").exists()
}
// assert is_valid_path_dep(std::path::Path::new(dep_path)) before declaring the dependency

Prevention

When it happens

Trigger: Declaring a dependency with `path = "./src/lib.rs"` or any path that points at a file rather than a directory; `is_embedded` returns true for a path that also satisfies `is_file()`.

Common situations: Confusing Cargo's path deps (which take a directory) with the embedded `[lib] path = "src/lib.rs"` syntax; pointing at a single-file crate from another workspace; refactoring a sub-crate into a file and forgetting to update dependents.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/5e698ba46e9b31b9.json. Report an issue: GitHub.