vercel/turborepo · error
lockfile should be in repo
Error message
lockfile should be in repo
What it means
ChangeMapper::lockfile_changed (change_mapper/mod.rs:335) anchors the detected lockfile path against the repo root with turbo_root.anchor(lockfile_path) and `.expect("lockfile should be in repo")` panics when the lockfile is not underneath the root turbo inferred. The invariant assumes package-manager discovery only ever finds the lockfile inside the workspace; when a layout breaks that (nested checkouts, root inference picking the wrong directory), this panic aborts the run.
Source
Thrown at crates/turborepo-repository/src/change_mapper/mod.rs:335
}
fn get_changed_packages_from_lockfile(
&self,
lockfile_content: &[u8],
) -> Result<Vec<ExternalDependencyChange>, ChangeMapError> {
self.pkg_graph
.changed_packages_from_lockfile_contents(lockfile_content)
.map_err(Into::into)
}
pub fn lockfile_changed(
turbo_root: &AbsoluteSystemPath,
changed_files: &HashSet<AnchoredSystemPathBuf>,
lockfile_path: &AbsoluteSystemPath,
) -> bool {
let lockfile_path_relative = turbo_root
.anchor(lockfile_path)
.expect("lockfile should be in repo");
changed_files.iter().any(|f| f == &lockfile_path_relative)
}
}
#[derive(thiserror::Error, Debug)]
pub enum ChangeMapError {
#[error(transparent)]
Wax(#[from] wax::BuildError),
#[error(transparent)]
ChangedPackages(#[from] ChangedPackagesError),
}
#[cfg(test)]
mod test {
use std::collections::HashSet;
use test_case::test_case;View on GitHub (pinned to f9245100cf)
Solutions
- Run turbo from the actual repository root so the lockfile lands inside the inferred root
- Verify the inferred root (inspect `turbo run <task> --dry-run=json` root/workspace data) and fix the layout or config that misdirects it
- Ensure the lockfile and workspace config (pnpm-workspace.yaml etc.) are inside the checked-out tree, not above it
- If the layout is legitimate, report it — the expect should become a real error message
Example fix
# before: run from nested checkout, lockfile one level up cd repo/apps/web && turbo run build # panics: lockfile should be in repo # after: run from the root that contains the lockfile cd repo && turbo run build --filter=web
Defensive patterns
Strategy: validation
Validate before calling
// before change detection, assert the invariant the panic encodes
let rel = turbo_root.anchor(lockfile_path);
if rel.is_err() {
anyhow::bail!("lockfile {lockfile_path} is outside turbo root {turbo_root}; run from the repo root");
} Prevention
- Always invoke turbo from the root that contains the lockfile
- Keep workspace config and lockfile inside the checked-out tree
- Add a CI sanity step asserting the lockfile is within the detected root
When it happens
Trigger: `turbo run` during change detection (watch mode / affected) where the lockfile detected via packageManager inference sits above the directory turbo treats as root — e.g. a partial/nested checkout of a monorepo, or root inference landing on a subdir while pnpm-workspace.yaml/lockfile live at the parent.
Common situations: Sparse or nested checkouts of a monorepo Running turbo from a subdirectory in layouts where the lockfile is one level above the inferred root Unusual TURBO_ROOT / discovery configuration after repo restructuring
Related errors
- non-root
- May not specify workspace name in non-root turbo.json
- New workspace root detected - unexpected 'workspaces' field
- Found both turbo.json and turbo.jsonc in the same directory:
- Found both turbo.json and turbo.jsonc in the same directory:
AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17).
Data as JSON: /api/errors/83026084df4a55bd.
Report an issue: GitHub.