{"record":{"id":"35f0e4e0c88b083e","repo":"Hmbown/CodeWhale","slug":"dsh-is-not-connected-nothing-to-remove","errorCode":null,"errorMessage":"DSH is not connected; nothing to remove","messagePattern":"DSH is not connected; nothing to remove","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/integrations/dsh/mod.rs","lineNumber":887,"sourceCode":"            \"bundle_dir\": paths.bundle_dir.display().to_string(),\n            \"patch_sha256\": bundle_record.patch_sha256,\n            \"app_bundle\": app.package_name(),\n        }),\n    );\n    Ok(bundle_record)\n}\n\n/// `dsh plugin --profile codewhale remove codewhale-dsh-bundle`, then delete\n/// only the Codewhale-owned bundle files. The DSH profile directory (and the\n/// app bundle link dsh recorded there) is DSH-owned and is left in place.\npub(crate) fn remove_bundle(\n    paths: &DshPaths,\n    detection: &DshDetection,\n    runner: &dyn DshRunner,\n) -> Result<Vec<PathBuf>> {\n    let mut doc = DshReceiptDocument::load(&paths.receipt)?;\n    let Some(mut record) = doc.current.take() else {\n        anyhow::bail!(\"DSH is not connected; nothing to remove\");\n    };\n    let Some(bundle_record) = record.bundle.take() else {\n        anyhow::bail!(\"no bundle is installed\");\n    };\n    let outcome = bundle::remove_from_profile(runner, detection)?;\n    let removed = bundle::remove_bundle_files(&paths.bundle_dir)?;\n    let now = now_rfc3339();\n    record.updated_at = now.clone();\n    doc.push(DshReceiptEntry {\n        event: DshReceiptEvent::RemoveBundle,\n        at: now,\n        codewhale_version: codewhale_version(),\n        dsh_version: detection.version.clone(),\n        dsh_home: detection.dsh_home.clone(),\n        overlay_sha256: Some(record.overlay_sha256.clone()),\n        skin_sha256: record.skin_sha256.clone(),\n        identity_summary: Some(identity_summary(&record.identity)),\n        permission_mode: Some(record.identity.permission_mode.as_str().to_string()),","sourceCodeStart":869,"sourceCodeEnd":905,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/integrations/dsh/mod.rs#L869-L905","documentation":"Removing the installed DSH bundle requires a 'current' connection record in the DSH receipt document. When the receipt has no current record — meaning DSH was never connected or the connection was already removed — this anyhow::bail! aborts the removal flow before touching the profile or bundle files.","triggerScenarios":"Calling the DSH disconnect/remove flow (e.g. `codewhale dsh disconnect`) when `doc.current` is None: DSH was never connected in this workspace, the receipt file is missing (load creates an empty document), or a prior removal already took the current record.","commonSituations":"Running disconnect twice; deleting or resetting the DSH receipt file while assuming a connection still exists; a fresh checkout or new workspace where setup was never run.","solutions":["Check connection state first with the DSH status/connect flow before attempting removal","Only run the remove command after a successful `codewhale dsh connect`","If you believe DSH is connected, inspect the receipt file at the DshPaths.receipt location and re-run connect to repopulate the current record"],"exampleFix":"// before\nremove_bundle(paths, detection, runner)?; // bails when not connected\n// after\nif dsh_is_connected(&paths)? {\n    remove_bundle(paths, detection, runner)?;\n}","handlingStrategy":"validation","validationCode":"if !std::path::Path::new(&paths.receipt).exists() { eprintln!(\"DSH not connected; run connect first\"); return; }","typeGuard":null,"tryCatchPattern":"match remove_bundle_result { Err(e) if e.to_string().contains(\"not connected\") => { /* treat as no-op */ }, Err(e) => return Err(e), Ok(removed) => { /* use removed */ } }","preventionTips":["Track DSH connection state in your tooling before issuing remove","Never delete the receipt file manually; use the connect/disconnect flow","Treat double-remove as expected in idempotent cleanup scripts"],"tags":["dsh","state-error","cli"],"backgroundTag":"invalid-state-transition","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}