vercel/turborepo · warning
Remote cache is read-only, skipping upload
Error message
Remote cache is read-only, skipping upload
What it means
In CacheMultiplexer::put (crates/turborepo-cache/src/multiplexer.rs:147-169), when a remote cache is configured but remote.write is false, the HTTP upload is skipped. To avoid spamming one warning per task, a should_print_skipping_remote_put flag prints the notice exactly once per run; cache reads from remote may still happen.
Source
Thrown at crates/turborepo-cache/src/multiplexer.rs:158
if self.cache_config.local.write {
self.fs
.as_ref()
.map(|fs| fs.put(anchor, key, files, duration))
.transpose()?;
}
let http_result = match self.get_http_cache() {
Some(http) => {
if self.cache_config.remote.write {
let http_result = http.put(anchor, key, files, duration).await;
Some(http_result)
} else {
if self
.should_print_skipping_remote_put
.load(Ordering::Relaxed)
{
turborepo_log::warn(
turborepo_log::Source::turbo(turborepo_log::Subsystem::Cache),
"Remote cache is read-only, skipping upload",
)
.emit();
self.should_print_skipping_remote_put
.store(false, Ordering::Relaxed);
}
// Cache is functional but running in read-only mode, so we don't want to try to
// write to it
None
}
}
_ => None,
};
match http_result {
Some(Err(CacheError::ApiClientError(
box turborepo_api_client::Error::CacheDisabled { .. },View on GitHub (pinned to f9245100cf)
Solutions
- If writes are intended, remove --remote-cache-read-only from the command/config so uploads resume.
- If read-only is intentional (consuming a shared cache), ignore the informational warning — it prints once per run.
- Check turbo.json cache/remoteCache settings and env vars for a lingering read-only option in CI templates.
- Verify directionality: ensure the producer pipeline writes with the flag off and only consumers run read-only.
Example fix
# before: producer also runs read-only, so it never uploads turbo run build --remote-cache-read-only # after: producer uploads, consumers stay read-only # producer: turbo run build # consumer: turbo run build --remote-cache-read-only
Defensive patterns
Strategy: validation
Validate before calling
#!/usr/bin/env bash # producer jobs must not run read-only if [[ "$PRODUCER" == "true" && "$*" == *--remote-cache-read-only* ]]; then echo "producer pipeline must upload — remove --remote-cache-read-only" >&2 exit 1 fi turbo run build "$@"
Prevention
- Split pipelines into producer (writable) and consumer (read-only) roles and lint flags per role.
- Grep CI logs for 'Remote cache is read-only' in producer jobs; treat it as a misconfiguration.
- Document why read-only exists (shared golden caches) so operators know when it is intentional.
When it happens
Trigger: Running with --remote-cache-read-only (or the corresponding turbo.json cache configuration / TURBO_CACHE_* env) while signed into a remote cache. Every put() with an http cache configured and cache_config.remote.write == false hits this branch once.
Common situations: Read-only caches are intentional for sharing a golden cache with dependents (e.g. a parent repo consuming a child repo's artifacts, or CI jobs that must not overwrite promoted artifacts), or someone left the flag on globally in CI scripts and wonders why hit rates never improve from their builds.
Related errors
- no caches are enabled
- --affected could not determine changed files. All tasks will
- {pad}• {base_msg}
- 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/0323258f082ff748.
Report an issue: GitHub.