vercel/turborepo · warning
{message}
Error message
{message} What it means
In `turbo watch`, each rebuilt run constructs a fresh RunBuilder with its own LogSinks (crates/turborepo-lib/src/run/watch.rs:341-352). Like the one-shot run command, it checks turborepo_shim::GLOBAL_WARNING_ENV_VAR — set by the shim when it fell back to the globally installed turbo — re-emits the stored message as a Shim-subsystem warning through the new sinks, then removes the variable so it prints once per watch session.
Source
Thrown at crates/turborepo-lib/src/run/watch.rs:344
_package_watcher: package_watcher,
_package_changes_watcher: package_changes_watcher,
hash_watcher,
};
let output_watcher: Arc<dyn OutputWatcher> =
Arc::new(InProcessOutputWatcher { glob_watcher });
let new_base = base.clone();
let mut run_builder =
RunBuilder::new(new_base, None)?.with_output_watcher(output_watcher.clone());
if let Some(ref qs) = query_server {
run_builder = run_builder.with_query_server(qs.clone());
}
let sinks = LogSinks::new(base.color_config);
sinks.init_logger();
if let Ok(message) = env::var(turborepo_shim::GLOBAL_WARNING_ENV_VAR) {
turborepo_log::warn(
turborepo_log::Source::turbo(turborepo_log::Subsystem::Shim),
message,
)
.emit();
unsafe { env::remove_var(turborepo_shim::GLOBAL_WARNING_ENV_VAR) };
}
if verbosity > 0 {
if let Ok(path) = subscriber.redirect_stderr_to_file(base.repo_root.as_std_path()) {
tracing::debug!("Verbose tracing redirected to {path}");
}
}
let (run, _analytics) = run_builder.build(&handler, telemetry.clone()).await?;
let run = Arc::new(run);
let watched_packages = run.get_relevant_packages();
View on GitHub (pinned to f9245100cf)
Solutions
- Install turbo locally: add it to devDependencies with an exact version and run the package manager install so the shim uses node_modules/.bin/turbo.
- Confirm the local binary: ./node_modules/.bin/turbo --version should match package.json.
- If the global must be used (e.g. a container image), acknowledge the warning or set TURBO_GLOBAL_WARNING_DISABLED=1.
- Keep watch sessions on the repo-pinned version to avoid behavior differences between contributors.
Example fix
# before: watch runs on global turbo
npm i -g turbo && turbo watch build # -> No locally installed `turbo` found...
# after: pin and install locally
"devDependencies": { "turbo": "2.3.3" }
pnpm install
pnpm exec turbo watch build Defensive patterns
Strategy: validation
Validate before calling
#!/usr/bin/env bash # guard watch runs on the local binary if [ ! -x node_modules/.bin/turbo ]; then echo "turbo watch requires the repo-local install — run pnpm/npm install" >&2 exit 1 fi exec ./node_modules/.bin/turbo watch build
Prevention
- Pin turbo in devDependencies and start watch via the package manager (pnpm exec turbo watch ...).
- Preflight node_modules/.bin/turbo in dev-container entrypoints.
- If the global binary is intentional for watch, set TURBO_GLOBAL_WARNING_DISABLED=1 to suppress the relayed message.
When it happens
Trigger: Starting `turbo watch` with a globally installed turbo while the repo has no node_modules/.bin/turbo (turbo missing from devDependencies or dependencies not installed). The shim sets the env var before delegating; the first watch loop iteration relays and clears it.
Common situations: Fresh clones or Docker images relying on global turbo during long watch sessions; version drift where the watcher silently uses a different turbo than the repo pins, which matters for watch reliability and cache compatibility across the team.
Related errors
- {message}
- File watcher still initializing after {}s, likely a large fi
- Found both turbo.json and turbo.jsonc in the same directory:
- Found both turbo.json and turbo.jsonc in the same directory:
- refusing to write structured log to symlink: {}
AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17).
Data as JSON: /api/errors/0d7336e9a8a14d86.
Report an issue: GitHub.