{"record":{"id":"b3964f8422f25fc4","repo":"influxdata/influxdb","slug":"ordered-catalog-batch-should-contain-changes","errorCode":null,"errorMessage":"ordered catalog batch should contain changes","messagePattern":"ordered catalog batch should contain changes","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"influxdb3_catalog/src/catalog/versions/v2.rs","lineNumber":710,"sourceCode":"    /// has a handle on the write permit at the time of invocation.\n    pub(crate) fn apply_ordered_catalog_batch(\n        &self,\n        batch: &OrderedCatalogBatch,\n        _permit: &CatalogWritePermit,\n    ) -> CatalogBatch {\n        let batch_sequence = batch.sequence_number().get();\n        let current_sequence = self.sequence_number().get();\n        assert_eq!(\n            batch_sequence,\n            current_sequence + 1,\n            \"catalog batch received out of order\"\n        );\n        let catalog_batch = self\n            .inner\n            .write()\n            .apply_catalog_batch(batch.batch(), batch.sequence_number(), Some(&self.store))\n            .expect(\"ordered catalog batch should succeed when applied\")\n            .expect(\"ordered catalog batch should contain changes\");\n        self.update_last_check_time();\n        catalog_batch.into_batch()\n    }\n\n    pub fn node(&self, node_id: &str) -> Option<Arc<NodeDefinition>> {\n        self.inner.read().nodes.get_by_name(node_id)\n    }\n\n    pub fn node_by_id(&self, node_id: &NodeId) -> Option<Arc<NodeDefinition>> {\n        self.inner.read().nodes.get_by_id(node_id)\n    }\n\n    pub fn list_nodes(&self) -> Vec<Arc<NodeDefinition>> {\n        self.inner.read().nodes.resource_iter().cloned().collect()\n    }\n\n    pub fn minimum_supported_row_delete_predicate_version(&self) -> Option<usize> {\n        self.inner","sourceCodeStart":692,"sourceCodeEnd":728,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_catalog/src/catalog/versions/v2.rs#L692-L728","documentation":"This panic fires when an ordered catalog batch, which has already been validated by apply_catalog_batch, returns None (no changes) instead of a CatalogBatch. The library considers a successfully-applied ordered batch to always contain at least one change; an empty result indicates a corrupted or out-of-order batch stream, so it panics rather than silently proceeding.","triggerScenarios":"Applying an ordered catalog batch whose underlying changes produce no mutations (e.g. replaying an already-applied batch, an empty batch slipping through sequence handling, or a batch whose writes were deduplicated away).","commonSituations":"Catalog replay/bootstrap against a persisted store where sequence numbers and stored state diverge; software upgrades changing batch persistence formats; concurrent writers corrupting the ordered batch queue.","solutions":["Verify the batch being replayed is not already applied (check its sequence number against the store's last applied sequence).","Inspect the persisted catalog store (influxdb3 data directory) for corruption or stale sequence state; restore from a known-good snapshot if corrupted.","Ensure only one writer produces ordered batches at a time; check for duplicate nodes pointing at the same catalog store.","Upgrade influxdb3 to the latest patch release; known issues in batch application have been fixed in later versions.","File an issue with the batch contents if the state appears consistent — this panic indicates an internal invariant break."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before replaying an ordered batch\nlet last_seq = store.last_applied_sequence();\nif batch.sequence_number() <= last_seq {\n    return Err(\"batch already applied\");\n}\nif batch.batch().is_empty() {\n    return Err(\"empty batch\");\n}","typeGuard":"fn batch_has_changes(batch: &CatalogBatch) -> bool {\n    !batch.batch().is_empty()\n}","tryCatchPattern":"match catalog.apply_ordered_batch(&batch) {\n    Ok(applied) => proceed(applied),\n    Err(e) => log::error!(\"ordered batch application failed: {e}\"),\n}\n// Note: the expect() panics — treat any panic in this path as fatal and restart from a consistent snapshot.","preventionTips":["Track and compare sequence numbers before applying batches","Never replay already-applied batches","Run a single catalog writer at a time","Keep catalog store snapshots for recovery"],"tags":["panic","catalog","invariant"],"backgroundTag":"internal-invariant-violation","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"}