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
- 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.
- Update the dependency declaration to reference the directory containing a valid `Cargo.toml` rather than the `.rs` file directly.
- 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
- Always point path dependencies at a directory containing a Cargo.toml, never at a raw .rs file.
- Add a CI check that every path dependency resolves to a package directory.
- Use `cargo metadata` to validate the manifest before committing path-dep changes.
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
- can only edit absolute paths, got
- can't find library ` `, rename file to `src/lib.rs` or…
- cannot mix `proc-macro` crate type with others
- cannot override `workspace.lints` in `lints`, either remove…
- cannot specify both `metabuild` and `build`
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
.urlView on GitHub (pinned to 98a09e7e7d)