rust-lang/cargo · error

single file packages cannot be used as dependencies

Error message

single file packages cannot be used as dependencies

What it means

When Cargo loads a `Path` source via `SourceId::load`, it converts the source URL to a filesystem path and checks two conditions: whether the path is an embedded (single-file) package (`is_embedded(&path)`) and whether that path points at a file rather than a directory. Single-file packages (e.g. a single `main.rs`/`lib.rs`) are valid as a workspace root but are explicitly rejected when the path source is being loaded as a dependency of another package. The bail happens before a `PathSource` is constructed.

Solutions

  1. Convert the single-file package into a proper Cargo package: create a directory containing a `Cargo.toml` and the source file under `src/lib.rs` or `src/main.rs`, then point the dependency path at that directory.
  2. Update the dependency declaration to reference the directory containing a valid `Cargo.toml` rather than the `.rs` file directly.
  3. If you need the single file only as a build target and not a dependency, move it to a workspace member rather than a path dependency.

Example fix

# before
[dependencies]
my-lib = { path = "./libs/single.rs" }

# after (create ./libs/my-lib/Cargo.toml + ./libs/my-lib/src/lib.rs)
[dependencies]
my-lib = { path = "./libs/my-lib" }
Defensive patterns

Strategy: validation

Validate before calling

// before adding a path dependency, ensure it points at a directory with a Cargo.toml
use std::path::Path;
fn is_valid_path_dep(p: &Path) -> bool {
    p.is_dir() && p.join("Cargo.toml").exists()
}
assert!(is_valid_path_dep(Path::new("./libs/my-lib")));

Prevention

When it happens

Trigger: Declaring a path dependency that points directly at a single `.rs` file identified as embedded, e.g. `my-dep = { path = "./libs/single.rs" }`, then resolving/loading that dependency's source. The check `crate::workspace::parser::is_embedded(&path) && path.is_file()` is true.

Common situations: Pointing a path dependency at a standalone `.rs` file instead of a directory containing a `Cargo.toml`; migrating a single-file experiment to a dependency without restructuring it into a proper package; tooling that auto-generates path deps from file paths.

Related errors


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

Appendix: source

Thrown at src/workspace/source_id.rs:403

    /// 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 98a09e7e7d)