{"record":{"id":"ae9c42723f4e140a","repo":"risingwavelabs/risingwave","slug":"output-column-must-exist-in-the-source-catalog","errorCode":null,"errorMessage":"output column must exist in the source catalog","messagePattern":"output column must exist in the source catalog","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/frontend/src/optimizer/plan_node/logical_iceberg_intermediate_scan.rs","lineNumber":181,"sourceCode":"\n    /// Fields carrying the iceberg-side column types (before the engine-table Hummock\n    /// type remapping), for predicate pushdown. Derived from the source catalog, which\n    /// the remapping never touches.\n    fn iceberg_side_fields(&self) -> Vec<Field> {\n        let catalog = self\n            .core\n            .catalog\n            .as_ref()\n            .expect(\"iceberg intermediate scan must have a source catalog\");\n        let by_name: HashMap<&str, &ColumnCatalog> =\n            catalog.columns.iter().map(|c| (c.name(), c)).collect();\n        self.core\n            .column_catalog\n            .iter()\n            .map(|col| {\n                let source_col = by_name\n                    .get(col.name())\n                    .expect(\"output column must exist in the source catalog\");\n                Field::from(&source_col.column_desc)\n            })\n            .collect()\n    }\n\n    pub fn output_columns(&self) -> impl ExactSizeIterator<Item = &str> {\n        self.core.column_catalog.iter().map(|c| c.name.as_str())\n    }\n\n    pub fn add_predicate(\n        &self,\n        iceberg_predicate: Predicate,\n        extracted_condition: Condition,\n    ) -> Self {\n        LogicalIcebergIntermediateScan {\n            iceberg_predicate: self.iceberg_predicate.clone().and(iceberg_predicate),\n            hummock_rewrite: self.hummock_rewrite.add_predicate(extracted_condition),\n            ..self.clone()","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/frontend/src/optimizer/plan_node/logical_iceberg_intermediate_scan.rs#L163-L199","documentation":"While mapping the node's output columns back to the original Iceberg source catalog, `iceberg_side_fields` expects every output column name to exist in the source catalog. A missing name means the intermediate scan produces a column the source doesn't have — an internal consistency violation, panicked via `.expect` during predicate pushdown.","triggerScenarios":"`predicate_pushdown` on a LogicalIcebergIntermediateScan where a column in `core.column_catalog` has no matching name in the source catalog's columns (e.g. after a rewrite added/renamed columns without updating the scan node).","commonSituations":"Optimizer rewrite bugs around Iceberg intermediate scans (column pruning/renaming passes) or mismatched node construction in tests.","solutions":["Verify that every output column of the intermediate scan is derived from the source catalog and names are kept in sync through rewrites.","Return a Result with a descriptive error instead of `.expect` to aid diagnosis.","Capture the failing plan (EXPLAIN) and minimal query, and file a bug against the Iceberg intermediate scan rewrite passes."],"exampleFix":"// before\nlet source_col = by_name.get(col.name())\n    .expect(\"output column must exist in the source catalog\");\n\n// after\nlet source_col = by_name.get(col.name()).ok_or_else(|| {\n    anyhow!(\"output column {:?} not found in iceberg source catalog\", col.name())\n})?;","handlingStrategy":"validation","validationCode":"// before pushdown, verify column alignment\nfor col in &scan.core.column_catalog {\n    if !scan.core.catalog.as_ref().unwrap().columns.iter().any(|c| c.name() == col.name()) {\n        return Err(format!(\"column {} missing in source catalog\", col.name()));\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep output column names synced with the source catalog through rewrites","Test column pruning/renaming passes against Iceberg scans","Replace expect with Result errors carrying the offending column name","Capture EXPLAIN output before filing optimizer bugs"],"tags":["rust","iceberg","optimizer","assertion"],"backgroundTag":"internal-invariant-violation","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}