{"record":{"id":"54f3a231a8026e90","repo":"Hmbown/CodeWhale","slug":"typed-config-did-not-serialize-to-a-toml-table","errorCode":null,"errorMessage":"typed config did not serialize to a TOML table","messagePattern":"typed config did not serialize to a TOML table","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/config_bundles.rs","lineNumber":968,"sourceCode":"    }\n    if key.starts_with(\"auth.\") {\n        return ExportSection::Drop;\n    }\n    match scope {\n        BundleScope::Global => ExportSection::Global,\n        BundleScope::Project => ExportSection::Project,\n    }\n}\n\nfn config_document(config: &ConfigToml) -> Result<toml::map::Map<String, toml::Value>> {\n    // Serialize through TOML text before parsing to Value. Direct\n    // `Value::try_from` double-encodes datetime values held inside flattened\n    // `toml::Value` extras as the serializer's private marker table.\n    let text = toml::to_string(config).context(\"serializing typed config for bundle\")?;\n    let value: toml::Value =\n        toml::from_str(&text).map_err(|_| anyhow!(\"serialized typed config was not valid TOML\"))?;\n    let toml::Value::Table(mut table) = value else {\n        bail!(\"typed config did not serialize to a TOML table\");\n    };\n    // `selected_provider_id` is runtime parse state and is skipped by serde;\n    // restore the exact named-provider identity that ConfigStore writes.\n    table.insert(\n        \"provider\".to_string(),\n        toml::Value::String(config.provider_id().to_string()),\n    );\n    Ok(table)\n}\n\n/// Return a recursively scrubbed export value. Secret-bearing leaves and\n/// machine-local paths are omitted rather than replaced with a placeholder,\n/// because a placeholder would become literal config on re-import.\nfn sanitize_export_value(path: &str, value: &toml::Value) -> Option<toml::Value> {\n    sanitize_export_value_at(path, value, 0)\n}\n\nfn sanitize_export_value_at(path: &str, value: &toml::Value, depth: usize) -> Option<toml::Value> {","sourceCodeStart":950,"sourceCodeEnd":986,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/cli/src/config_bundles.rs#L950-L986","documentation":"config_document serializes the typed ConfigToml to TOML, re-parses it, and expects the top-level value to be a table. If toml::to_string produced anything other than a root table (an internal invariant — a struct always serializes to a table), the export/import pipeline bails rather than proceeding with a malformed document. The round-trip exists to avoid double-encoding datetime values held in flattened extras.","triggerScenarios":"export_bundle, prepare_import, or apply_config_value calls config_document and the toml round-trip yields a non-table root — essentially only possible when the serialized output is an array or scalar, which for ConfigToml would indicate a serde/serialization bug or a corrupted typed config.","commonSituations":"Rare: a codewhale-config version change altering the serializer's output shape; a hand-edited or corrupted config source that deserializes into an unexpected shape; a bug in custom serde impls.","solutions":["Inspect the config file for structurally invalid top-level content (an array or bare value instead of key/value sections) and fix it.","Verify the codewhale-config crate version matches the CLI; a mismatched pair can change serialization shape.","If it reproduces with a stock config, report it as a bug — this path is an internal invariant, not user input validation.","Regenerate a clean config (back up first) and retry the export/import."],"exampleFix":"// before (config.toml root)\n[[somewhere]]\nkey = \"value\"\n// after (root must be a table of sections)\n[provider]\nid = \"openai\"","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"if let toml::Value::Table(table) = &parsed {\n    // proceed with table\n}","tryCatchPattern":"match config_document(config) {\n    Ok(doc) => { /* use doc */ }\n    Err(e) if e.to_string().contains(\"did not serialize to a TOML table\") => {\n        eprintln!(\"serialization invariant broken; check codewhale-config version / config shape: {e:#}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Keep codewhale-config and the CLI on matching versions.","Avoid hand-editing the top-level structure of config.toml into non-table shapes.","Treat reproducible occurrences of this error as a bug report, not a config problem."],"tags":["serialization","toml","internal-invariant","config-bundles"],"backgroundTag":"toml-parse-error","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"}