{"record":{"id":"7b42f56779d306c0","repo":"influxdata/influxdb","slug":"table-should-exist-by-id","errorCode":null,"errorMessage":"table should exist by id","messagePattern":"table should exist by id","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"influxdb3_catalog/src/catalog/versions/v2/update.rs","lineNumber":1922,"sourceCode":"\n    pub fn table_or_create(&mut self, table_name: &str) -> Result<TableId> {\n        match self.table_transaction(table_name) {\n            Some(tx) => Ok(tx.table.table_id),\n            None => self.create_table(\n                table_name,\n                create_table_columns::none(),\n                None,\n                FieldFamilyMode::Aware,\n            ),\n        }\n    }\n\n    pub fn table_tx_or_create(&mut self, table_name: &str) -> Result<&mut TableTransaction> {\n        let id = self.table_or_create(table_name)?;\n        Ok(self\n            .tables\n            .get_mut_by_id(&id)\n            .expect(\"table should exist by id\"))\n    }\n\n    pub fn column_or_create(\n        &mut self,\n        table_name: &str,\n        column_name: &str,\n        column_type: InfluxColumnType,\n    ) -> Result<ColumnDefinition> {\n        let Some(table_tx) = self.table_transaction(table_name) else {\n            return Err(CatalogError::NotFound(table_name.to_string()));\n        };\n        match table_tx.table.column_definition(column_name) {\n            Some(def) if def.column_type() == column_type => Ok(def),\n            Some(def) => Err(CatalogError::InvalidColumnType {\n                column_name: Arc::clone(&def.name()),\n                expected: def.column_type(),\n                got: column_type,\n            }),","sourceCodeStart":1904,"sourceCodeEnd":1940,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_catalog/src/catalog/versions/v2/update.rs#L1904-L1940","documentation":"table_tx_or_create creates (or looks up) a table and then expects the resulting id to be present in self.tables. Since table_or_create is expected to have inserted a TableTransaction for that id, get_mut_by_id returning None means the insert path skipped the transaction (e.g. the table already existed and the else branch returned None upstream of a broken assumption) or the map was mutated inconsistently.","triggerScenarios":"Calling table_tx_or_create when table_or_create returned an existing table's id without inserting a TableTransaction for it into self.tables, so the subsequent get_mut_by_id finds nothing.","commonSituations":"Write paths that touch an already-existing table but expect an open table transaction; batches built through mixed legacy/new APIs where the existing table was never registered as a transaction.","solutions":["Prefer obtaining the transaction from the same call: use table_tx_or_create rather than mixing table_or_create with separate map lookups","Ensure every path that returns a table_id also inserts a TableTransaction keyed by that id in the same batch","Check the library version for a fix to the existing-table branch of table_or_create and upgrade","If reproducible on the latest version, file a bug with the failing call sequence"],"exampleFix":"// before\nlet id = batch.table_or_create(\"cpu\")?;\nlet tx = batch.get_mut_by_id(&id).expect(\"table should exist by id\");\n// after\nlet tx = batch.table_tx_or_create(\"cpu\")?; // single source of truth","handlingStrategy":"validation","validationCode":"// confirm the table exists in the schema before requesting a transaction\nif db_schema.table_id(table_name).is_none() && !batch.will_create_table(table_name) {\n    return Err(anyhow!(\"table {} unknown and not scheduled for creation\", table_name));\n}","typeGuard":"fn tx_for<'a>(batch: &'a mut CatalogBatch, id: &TableId) -> Option<&'a mut TableTransaction> {\n    batch.tables.get_mut_by_id(id)\n}","tryCatchPattern":"let Some(tx) = batch.tables.get_mut_by_id(&id) else {\n    return Err(anyhow!(\"no table transaction for id {id:?}; create it first\"));\n};","preventionTips":["Use table_tx_or_create instead of separate lookup+expect","Ensure every table_id returned also has a transaction inserted in the same batch","Add debug_assert!s when building batches to catch missing transactions early","Stay on a library version where the existing-table path inserts a transaction"],"tags":["rust","panic","catalog","lookup"],"backgroundTag":"resource-not-found","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}