{"record":{"id":"eda3584bfc8e3ddb","repo":"Hmbown/CodeWhale","slug":"overlay-is-stale-run-cli-command-update-befor","errorCode":null,"errorMessage":"overlay is stale; run `{CLI_COMMAND} update` before install-bundle","messagePattern":"overlay is stale; run `(.+?) update` before install-bundle","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/integrations/cli.rs","lineNumber":393,"sourceCode":"        DshIntegrationCommand::Enable => {\n            let paths = DshPaths::from_process()?;\n            let record = dsh::set_disabled(&paths, false)?;\n            println!(\"enabled: {}\", record.overlay_path.display());\n            Ok(())\n        }\n        DshIntegrationCommand::InstallBundle { app, yes } => {\n            let app = dsh::DshAppBundle::parse(&app)\n                .ok_or_else(|| anyhow::anyhow!(\"--app must be `web` or `headless`, got `{app}`\"))?;\n            let (paths, report) = status_report(config, workspace, false)?;\n            ensure_launchable_dsh(&report)?;\n            let record = report.record.as_ref().ok_or_else(|| {\n                anyhow::anyhow!(\"DSH is not connected; run `{CLI_COMMAND} connect` first\")\n            })?;\n            if let dsh::BundleAvailability::NotAvailable { reason } = &report.bundle_availability {\n                anyhow::bail!(\"DSH plugin path not available: {reason}\");\n            }\n            if matches!(report.state, DshIntegrationState::StaleConfig { .. }) {\n                anyhow::bail!(\"overlay is stale; run `{CLI_COMMAND} update` before install-bundle\");\n            }\n            let app_source = dsh::bundle::app_bundle_source(\n                report\n                    .detection\n                    .binary\n                    .as_ref()\n                    .ok_or_else(|| anyhow::anyhow!(\"dsh binary path is unknown\"))?,\n                app,\n            )?;\n            let profile_dir = report\n                .detection\n                .dsh_home\n                .join(\"profiles\")\n                .join(dsh::bundle::BUNDLE_PROFILE);\n            println!(\"{RELATIONSHIP_LABEL} — install-bundle plan (nothing written yet)\");\n            println!(\n                \"  will write (Codewhale-owned): {}/{{package.json,cordis.patch.yml,README.md,NOTICE.md}}\",\n                paths.bundle_dir.display()","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/integrations/cli.rs#L375-L411","documentation":"`install-bundle` refuses to run while `report.state` is `StaleConfig`: the overlay exists on disk but no longer matches the current Codewhale route (the overlay's SHA-256 drifted from the receipt's because provider, model, base_url, or workspace changed). Installing a bundle on top of a stale overlay would pin the bundle to an identity the user has already moved away from, so the CLI forces `update` first to re-pin the identity.","triggerScenarios":"`install-bundle` after changing the provider or default model in Codewhale config since the last `connect`/`update`; after hand-editing `codewhale.patch.yml`; after pointing Codewhale at a different workspace directory. The same guard pattern exists in `launch_spec` (dsh/mod.rs:630-634) with a matching message.","commonSituations":"Switching default model and immediately trying install-bundle; editing the generated overlay manually (its header says do not edit); running Codewhale from a different workspace than the one the overlay was generated for.","solutions":["Run `codewhale integrations dsh update` to regenerate the overlay for the current route, then retry install-bundle","If you hand-edited the overlay, let `update` rewrite it — the file is marked generated","Use `codewhale integrations dsh status` to read the staleness reason and confirm it clears after update"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let (_paths, report) = status_report(config, workspace, false)?;\nif matches!(report.state, DshIntegrationState::StaleConfig { .. }) {\n    println!(\"overlay is stale; run `codewhale integrations dsh update` first\");\n    return Ok(());\n}","typeGuard":"fn overlay_fresh(report: &DshStatusReport) -> bool {\n    !matches!(report.state, DshIntegrationState::StaleConfig { .. })\n}","tryCatchPattern":null,"preventionTips":["Run `update` after every provider/model/workspace change — it is cheap and re-pins the overlay","Never hand-edit codewhale.patch.yml; its SHA-256 is the drift detector","Gate bundle and launch flows on the typed state enum, not on file existence"],"tags":["rust","dsh","state","drift","overlay"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}