vercel/turborepo · error
non-root
Error message
non-root
What it means
During workspace discovery (discovery.rs:169 region), turbo globs package.json files and, per path, joins parent().join_component("turbo.json"). The `.expect("non-root")` panics when a discovered package.json path has no parent — which on a filesystem is only true for the root itself (/package.json or a drive root). In practice it means discovery started scanning at (or matched) the filesystem root.
Source
Thrown at crates/turborepo-repository/src/discovery.rs:193
return Ok(DiscoveryResponse {
workspaces: package_paths
.into_iter()
.map(|package_json| WorkspaceData {
package_json,
turbo_json: None,
})
.collect(),
package_manager: self.package_manager.clone(),
});
}
// `buffered` keeps discovery order deterministic while letting the
// per-workspace turbo.json stats run concurrently — sequentially
// these 1-per-workspace syscalls cost ~20ms on large monorepos.
futures::stream::iter(package_paths.into_iter().map(|path| async move {
let potential_turbo = path
.parent()
.expect("non-root")
.join_component("turbo.json");
let potential_turbo_exists = tokio::fs::try_exists(potential_turbo.as_path()).await;
Ok(WorkspaceData {
package_json: path,
turbo_json: potential_turbo_exists
.unwrap_or_default()
.then_some(potential_turbo),
})
}))
.buffered(64)
.collect::<Vec<Result<WorkspaceData, Error>>>()
.instrument(tracing::info_span!("turbo_json_stat_stream"))
.await
.into_iter()
.collect::<Result<Vec<_>, _>>()
.map(|workspaces| DiscoveryResponse {
workspaces,View on GitHub (pinned to 7fe373bc27)
Solutions
- Run turbo from inside an actual project directory (check `pwd` in CI before the turbo step)
- Fix workspace/root configuration so discovery anchors inside the repo, not at /
- If a package.json legitimately exists at your filesystem root, move it — it breaks more than turbo
- Report the glob config + cwd if the cause is not obvious
Example fix
# before (CI step) workdir: / run: turbo run build # after workdir: /home/runner/work/repo/repo run: turbo run build
Defensive patterns
Strategy: validation
Validate before calling
// guard discovery inputs: every package.json must have a parent
for p in package_paths {
if p.parent().is_none() {
anyhow::bail!("discovery produced root-level package.json: {p}");
}
} Type guard
fn has_parent(p: &std::path::Path) -> bool { p.parent().map(|x| !x.as_os_str().is_empty()).unwrap_or(false) } Prevention
- CI: verify the workdir is the mounted project before running turbo
- Never keep package.json at / or drive roots
- Sanity-check absolute-rooted glob patterns in workspace config
When it happens
Trigger: Workspace discovery producing `/package.json` (Unix) or `C:\package.json` (Windows) as a candidate — degenerate glob root, running turbo with cwd = filesystem root and a config that makes discovery walk upward to /, or a broken root/workspace glob.
Common situations: CI containers whose workdir is / with no project mounted Glob/workspace configuration mistakes (empty or absolute-rooted patterns) Practically never in normal checkouts
Related errors
- lockfile should be in repo
- joined path is absolute and valid utf8: {err:?}
- collapsed path should be absolute: {err:?}
- clean should produce valid UTF-8: {err:?}
- anchored system path is relative: {}
AI-assisted analysis of vercel/turborepo@7fe373bc27 (2026-08-17).
Data as JSON: /api/errors/9bce99ec55a747eb.
Report an issue: GitHub.