{"record":{"id":"2c0f7f18fcc1ff8d","repo":"dbt-labs/dbt-core","slug":"extension-dispatch-only-yields-csv-as-none-not-ta","errorCode":null,"errorMessage":"extension dispatch only yields csv as None, not TableFormat::Csv","messagePattern":"extension dispatch only yields csv as None, not TableFormat::Csv","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-tasks-sa/src/register_seeds.rs","lineNumber":257,"sourceCode":"                let type_ops = Arc::clone(&type_ops);\n                handles.push(spawn_blocking_traced(move || {\n                    register_seed_csv(seed, ctx, type_ops)\n                }))\n            }\n            Some(TableFormat::Json) => {\n                let type_ops = Arc::clone(&type_ops);\n                handles.push(spawn_blocking_traced(move || {\n                    register_seed_json(seed, ctx, type_ops)\n                }))\n            }\n            Some(TableFormat::Parquet) => {\n                let type_ops = Arc::clone(&type_ops);\n                handles.push(spawn_traced(register_seed_parquet_async(\n                    seed, ctx, type_ops,\n                )))\n            }\n            Some(TableFormat::Csv) => {\n                unreachable!(\"extension dispatch only yields csv as None, not TableFormat::Csv\")\n            }\n        }\n    }\n\n    let mut results = Vec::with_capacity(handles.len());\n    for handle in handles {\n        match handle.await {\n            Ok(Ok(registered)) => results.push(registered),\n            // Emit the real error here (CSV parse failure, etc.). The seed's\n            // visit_render will detect the missing schema and mark the task as\n            // failed without emitting a second error.\n            Ok(Err(e)) => tracing::error!(\"{}\", e),\n            Err(join_err) => {\n                tracing::error!(\"Seed registration task panicked: {}\", join_err)\n            }\n        }\n    }\n    results","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-tasks-sa/src/register_seeds.rs#L239-L275","documentation":"Seed pre-registration dispatches on the file format: CSV seeds are handled earlier (as the None format case), while Parquet and other table formats spawn parquet registration. A TableFormat::Csv value reaching this match means the extension-to-format dispatch produced Csv twice — once converted to None and once passed through — which the dispatch contract forbids. The panic flags a broken format-mapping layer.","triggerScenarios":"Calling pre_register_seeds on a seed whose file extension maps to TableFormat::Csv but where the earlier `None` arm was not taken — i.e. the format resolver returned Some(TableFormat::Csv) instead of None for csv extensions.","commonSituations":"Modifying the seed-format detection code so csv files are classified as TableFormat::Csv at this layer; adding a new extension mapping that bypasses the csv-to-None conversion; upstream changes in the format/table-format detection crate.","solutions":["Fix the format detection/dispatch so CSV seed files resolve to None (handled by the csv path) rather than Some(TableFormat::Csv).","Verify the extension-to-TableFormat mapping still special-cases csv before this match.","If csv handling moves to this layer, replace the unreachable arm with a real csv registration branch.","Check recently changed seed loading code for a duplicated format conversion."],"exampleFix":"// before\nSome(TableFormat::Csv) => unreachable!(\"extension dispatch only yields csv as None\"),\n\n// after\n// in format detection: TableFormat mapping returns None for .csv so the csv branch handles it\n\"csv\" => None, // csv seeds take the legacy csv registration path","handlingStrategy":"validation","validationCode":"let fmt = detect_table_format(path);\ndebug_assert!(fmt != Some(TableFormat::Csv), \"csv must map to None before pre_register_seeds\");","typeGuard":"fn is_parquet_dispatchable(fmt: Option<TableFormat>) -> bool { !matches!(fmt, Some(TableFormat::Csv)) }","tryCatchPattern":"Some(TableFormat::Csv) => {\n    log::warn!(\"csv reached parquet dispatch; falling back to csv registration\");\n    register_seed_csv(seed, ctx);\n}","preventionTips":["Keep the csv-to-None conversion in one place in the format detector.","Add a test asserting .csv files never yield Some(TableFormat::Csv) at the dispatch boundary.","Avoid duplicating format mapping logic across seed-loading call sites."],"tags":["seeds","file-format","dispatch","unreachable","rust"],"backgroundTag":"internal-invariant-violation","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}