{"record":{"id":"8f5ba5fac38b3969","repo":"Hmbown/CodeWhale","slug":"refusing-to-import-non-portable-config-path-dotted","errorCode":null,"errorMessage":"refusing to import non-portable config path {dotted}","messagePattern":"refusing to import non-portable config path (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/config_bundles.rs","lineNumber":1188,"sourceCode":"    let mut candidate = config_from_document(&document.to_string())?;\n    let mut model_edits = Vec::<(String, String, String)>::new();\n    let mut selected_provider = None;\n    for (section, table) in [\n        (\"preferences\", &bundle.preferences),\n        (\"profiles\", &bundle.profiles),\n        (\"plugins\", &bundle.plugins),\n        (\"project\", &bundle.project),\n        (\"global\", &bundle.global),\n    ] {\n        if !section_applies(section, scope) {\n            continue;\n        }\n        for (key, value) in &table.entries {\n            let dotted = format!(\"{section}.{key}\");\n            if nonportable_path_reason(key).is_some()\n                || value_rejection_reason(key, value).is_some()\n            {\n                bail!(\"refusing to import non-portable config path {dotted}\");\n            }\n            if key == \"provider\" {\n                selected_provider = Some(\n                    value\n                        .as_str()\n                        .ok_or_else(|| anyhow!(\"config entry {dotted:?} must be a string\"))?,\n                );\n                continue;\n            }\n            collect_model_edits(&dotted, key, value, &mut model_edits)?;\n            if codewhale_tui::route_preferences::is_route_key(key) {\n                continue;\n            }\n            apply_config_value(&mut candidate, key, value)?;\n        }\n    }\n    document = toml::to_string(&toml::Value::Table(config_document(&candidate)?))?\n        .parse()","sourceCodeStart":1170,"sourceCodeEnd":1206,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/config_bundles.rs#L1170-L1206","documentation":"During prepare_import each table entry is screened with nonportable_path_reason(key) and value_rejection_reason(key, value); if either rejects the entry, the import is refused because that dotted config path is not portable across machines (e.g. machine-local paths, secrets, or values of the wrong shape). The import aborts before any write rather than silently dropping entries.","triggerScenarios":"Importing a bundle whose config table contains a key flagged as non-portable (machine-specific path keys) or a value whose type/content is rejected for that key; raised from prepare_import via run_import/apply_bundle.","commonSituations":"Hand-editing a bundle and adding absolute filesystem paths or credential-like values; bundles generated on another OS where a path key is non-portable; exporting older config formats whose value types no longer validate.","solutions":["Open the bundle and remove/replace the offending `section.key` entry, then re-import.","Move machine-specific values out of the bundle — set them locally after import instead of shipping them in the file.","Re-export with `config export --portable` so the exporter strips non-portable paths at source."],"exampleFix":"// before (bundle.toml)\n[settings]\nhistory_path = \"/home/alice/.local/share/codewhale\"\n// after\n[settings]\n# history_path removed: machine-local; configure per machine","handlingStrategy":"validation","validationCode":"for (k, v) in bundle_table.iter() {\n    if nonportable_path_reason(k).is_some() || value_rejection_reason(k, v).is_some() {\n        eprintln!(\"non-portable entry: {k}\");\n    }\n}\n","typeGuard":"fn all_entries_portable(table: &toml::Table) -> bool {\n    table.iter().all(|(k, v)| nonportable_path_reason(k).is_none() && value_rejection_reason(k, v).is_none())\n}","tryCatchPattern":"if let Err(e) = run_import(&args, &store) {\n    if e.to_string().starts_with(\"refusing to import non-portable config path\") {\n        eprintln!(\"strip the named path from the bundle and retry\");\n    }\n}","preventionTips":["Always produce bundles via `config export --portable` rather than hand-writing them.","Keep absolute paths and machine-local settings out of shared bundles.","Validate value types against the config schema before importing."],"tags":["config","import","portability","validation"],"backgroundTag":"unsupported-config-value","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}