{"record":{"id":"7a9c3f04f53a9c7b","repo":"zeroclaw-labs/zeroclaw","slug":"source-workspace-matches-current-zeroclaw-workspac","errorCode":null,"errorMessage":"Source workspace matches current ZeroClaw workspace; refusing self-migration","messagePattern":"Source workspace matches current ZeroClaw workspace; refusing self-migration","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-runtime/src/migration.rs","lineNumber":41,"sourceCode":"    renamed_conflicts: usize,\n}\n\npub async fn migrate_openclaw_memory(\n    config: &Config,\n    source_workspace: Option<PathBuf>,\n    dry_run: bool,\n    reindex: bool,\n) -> Result<()> {\n    let source_workspace = resolve_openclaw_workspace(source_workspace)?;\n    if !source_workspace.exists() {\n        bail!(\n            \"OpenClaw workspace not found at {}. Pass --source <path> if needed.\",\n            source_workspace.display()\n        );\n    }\n\n    if paths_equal(&source_workspace, &config.data_dir) {\n        bail!(\"Source workspace matches current ZeroClaw workspace; refusing self-migration\");\n    }\n\n    let mut stats = MigrationStats::default();\n    let entries = collect_source_entries(&source_workspace, &mut stats)?;\n\n    if entries.is_empty() {\n        println!(\n            \"No importable memory found in {}\",\n            source_workspace.display()\n        );\n        println!(\"Checked for: memory/brain.db, MEMORY.md, memory/*.md\");\n        return Ok(());\n    }\n\n    if dry_run {\n        println!(\"🔎 Dry run: OpenClaw migration preview\");\n        println!(\"  Source: {}\", source_workspace.display().to_string());\n        println!(\"  Target: {}\", config.data_dir.display().to_string());","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-runtime/src/migration.rs#L23-L59","documentation":"After confirming the source workspace exists, migrate_openclaw_memory compares it against config.data_dir (the current ZeroClaw data directory) with paths_equal and refuses to continue if they are the same. The guard exists because migration reads from the source and writes into ZeroClaw's store; when they are one directory the migration would read and rewrite its own output, corrupting data.","triggerScenarios":"Passing --source that resolves to the ZeroClaw data dir itself; config.data_dir changed to point at the old OpenClaw directory (e.g. to \"adopt\" it in place); symlinks or different spellings of the same path (paths_equal normalizes, so /a/b vs /a/./b still collide).","commonSituations":"Adopt in place\" setups where users repoint data_dir at OpenClaw's folder and then run migration; container mounts that map both workspaces to the same volume; copy-pasting a tutorial's --source that happens to equal the install's data dir.","solutions":["Point --source at the original OpenClaw workspace, keeping it distinct from ZeroClaw's data dir","Check the current data dir (zeroclaw config get data_dir or equivalent) and make sure the two paths differ","If the data genuinely overlaps, move one workspace to a separate directory first, then re-run","If you already manually merged data, skip migration — nothing left to import"],"exampleFix":"# before\ndata_dir = \"/home/user/.openclaw\"   # zeroclaw.toml\nzeroclaw migrate-memory --source /home/user/.openclaw\n\n# after\ndata_dir = \"/home/user/.zeroclaw\"\nzeroclaw migrate-memory --source /home/user/.openclaw","handlingStrategy":"validation","validationCode":"let src = resolve_openclaw_workspace(source_workspace.clone())?;\nif paths_equal(&src, &config.data_dir) {\n    // refuse early with a targeted message; source and destination must be distinct stores\n    anyhow::bail!(\"source equals data_dir; refusing to migrate in place\");\n}","typeGuard":null,"tryCatchPattern":"Err(e) if e.to_string().contains(\"refusing self-migration\") => {\n    // config error: separate the two workspaces, then re-run; never bypass\n}","preventionTips":["Keep OpenClaw and ZeroClaw workspaces in separate directory trees","Before migrating, print both resolved paths for the operator to eyeball","Never point data_dir at the legacy workspace to 'adopt' it — migrate instead"],"tags":["rust","zeroclaw","migration","openclaw","data-safety","self-guard"],"backgroundTag":"circular-operation","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}