{"record":{"id":"0323258f082ff748","repo":"vercel/turborepo","slug":"remote-cache-is-read-only-skipping-upload","errorCode":null,"errorMessage":"Remote cache is read-only, skipping upload","messagePattern":"Remote cache is read-only, skipping upload","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/turborepo-cache/src/multiplexer.rs","lineNumber":158,"sourceCode":"        if self.cache_config.local.write {\n            self.fs\n                .as_ref()\n                .map(|fs| fs.put(anchor, key, files, duration))\n                .transpose()?;\n        }\n\n        let http_result = match self.get_http_cache() {\n            Some(http) => {\n                if self.cache_config.remote.write {\n                    let http_result = http.put(anchor, key, files, duration).await;\n\n                    Some(http_result)\n                } else {\n                    if self\n                        .should_print_skipping_remote_put\n                        .load(Ordering::Relaxed)\n                    {\n                        turborepo_log::warn(\n                            turborepo_log::Source::turbo(turborepo_log::Subsystem::Cache),\n                            \"Remote cache is read-only, skipping upload\",\n                        )\n                        .emit();\n                        self.should_print_skipping_remote_put\n                            .store(false, Ordering::Relaxed);\n                    }\n                    // Cache is functional but running in read-only mode, so we don't want to try to\n                    // write to it\n                    None\n                }\n            }\n            _ => None,\n        };\n\n        match http_result {\n            Some(Err(CacheError::ApiClientError(\n                box turborepo_api_client::Error::CacheDisabled { .. },","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/vercel/turborepo/blob/f9245100cf0d31d96628804ead485f6bf226e55a/crates/turborepo-cache/src/multiplexer.rs#L140-L176","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before: producer also runs read-only, so it never uploads\nturbo run build --remote-cache-read-only\n\n# after: producer uploads, consumers stay read-only\n# producer:\nturbo run build\n# consumer:\nturbo run build --remote-cache-read-only","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n# producer jobs must not run read-only\nif [[ \"$PRODUCER\" == \"true\" && \"$*\" == *--remote-cache-read-only* ]]; then\n  echo \"producer pipeline must upload — remove --remote-cache-read-only\" >&2\n  exit 1\nfi\nturbo run build \"$@\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["turborepo","remote-cache","read-only","cache-upload","ci"],"backgroundTag":"remote-cache-read-only","analyzedSha":"f9245100cf0d31d96628804ead485f6bf226e55a","analyzedAt":"2026-08-17T10:46:15.696Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}