vercel/turborepo · warning
{pad}• {base_msg}
Error message
{pad}• {base_msg} What it means
Before a run, turbo resolves a RemoteCacheStatus and formats it via remote_cache_status_message (crates/turborepo-lib/src/run/mod.rs:161-213). Enabled/disabled statuses are printed as info; the Unavailable family (CouldNotConnect, AuthenticationFailed, UsageLimitExceeded, SpendingPaused, DisabledForTeam, UnexpectedServerError) is emitted as this warning with the reason inline, so builds proceed local-cache-only.
Source
Thrown at crates/turborepo-lib/src/run/mod.rs:455
self.filtered_pkgs.len()
),
)
.emit();
}
let (base_msg, is_warning) = remote_cache_status_message(
self.remote_cache_status,
&self.opts.api_client_opts.api_url,
);
let cache_status = if self.opts.run_opts.is_shared_worktree_cache {
format!("{pad}• {base_msg}, using shared worktree cache")
} else {
format!("{pad}• {base_msg}")
};
if is_warning {
turborepo_log::warn(
turborepo_log::Source::turbo(turborepo_log::Subsystem::Run),
cache_status,
)
.emit();
} else {
turborepo_log::info(
turborepo_log::Source::turbo(turborepo_log::Subsystem::Run),
cache_status,
)
.emit();
}
turborepo_log::info(
turborepo_log::Source::turbo(turborepo_log::Subsystem::Run),
"",
)
.emit();
}
View on GitHub (pinned to f9245100cf)
Solutions
- Match the parenthesized reason: 'Authentication failed' -> refresh credentials (turbo login or rotate TURBO_TOKEN/TURBO_TEAM); 'Could not connect' -> check TURBO_API/network/proxy; 'Usage limit exceeded'/'Spending paused' -> billing/plan; 'Disabled for this team' -> team settings.
- Validate the token against the API endpoint manually (curl with the bearer token) to separate auth vs network issues.
- For self-hosted caches, verify the endpoint's health and TLS before rerunning turbo.
- Keep local caching on so builds degrade to local-only rather than fully cold.
Example fix
# before: stale CI token TURBO_TOKEN=old-token TURBO_TEAM=acme turbo run build # -> Remote caching unavailable (Authentication failed ...) # after: rotate the secret, verify, rerun curl -sS -H "Authorization: Bearer $TURBO_TOKEN" "$TURBO_API/v8/user" >/dev/null && echo ok TURBO_TOKEN=new-token TURBO_TEAM=acme turbo run build
Defensive patterns
Strategy: validation
Validate before calling
#!/usr/bin/env bash
# preflight remote cache before a long run
: "${TURBO_API:=https://api.vercel.com}"
if [ -n "$TURBO_TOKEN" ]; then
code=$(curl -s -o /dev/null -w '%{http_code}' \
-H "Authorization: Bearer $TURBO_TOKEN" "$TURBO_API/v8/user")
[ "$code" = 200 ] || { echo "remote cache auth preflight failed: HTTP $code" >&2; exit 1; }
fi
turbo run build Prevention
- Run a token preflight (curl the API with the bearer token) at the start of CI jobs.
- Rotate TURBO_TOKEN on a schedule and alert when runs report 'Remote caching unavailable'.
- Keep local caching enabled so degraded remote availability only slows, not breaks, builds.
When it happens
Trigger: Remote caching is configured (linked or TURBO_TOKEN present) but the preflight to the API fails: unreachable api url, invalid/expired token, team usage limit hit, spending paused, remote cache disabled for the team, or a 5xx from the server. is_warning=true only for Unavailable reasons.
Common situations: Expired TURBO_TOKEN in CI secrets, typo'd/stale TURBO_API, Vercel usage limits reached at month end, org spending pauses, or self-hosted cache endpoints being down. Builds succeed but every run is cold on remote.
Related errors
- no caches are enabled
- Remote cache is read-only, skipping upload
- 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/a2037e11836ceaaa.
Report an issue: GitHub.