{"record":{"id":"8027d523a1df95d2","repo":"risingwavelabs/risingwave","slug":"invalid-state-new-count-0-and-is-new-entry-is-t","errorCode":null,"errorMessage":"invalid state, new_count = 0 and is_new_entry is true","messagePattern":"invalid state, new_count = 0 and is_new_entry is true","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/executor/approx_percentile/global_state.rs","lineNumber":222,"sourceCode":"            sign_datum.clone(),\n            bucket_id_datum.clone(),\n            Datum::from(ScalarImpl::Int64(old_count)),\n        ];\n        if new_count == 0 && !is_new_entry {\n            self.bucket_state_table.delete(old_row);\n        } else if new_count > 0 {\n            let new_row = &[\n                sign_datum,\n                bucket_id_datum,\n                Datum::from(ScalarImpl::Int64(new_count)),\n            ];\n            if is_new_entry {\n                self.bucket_state_table.insert(new_row);\n            } else {\n                self.bucket_state_table.update(old_row, new_row);\n            }\n        } else {\n            bail!(\"invalid state, new_count = 0 and is_new_entry is true\")\n        }\n\n        Ok(())\n    }\n\n    pub async fn commit(&mut self, epoch: EpochPair) -> StreamExecutorResult<()> {\n        // Commit row count state.\n        let row_count_datum = Datum::from(ScalarImpl::Int64(self.row_count));\n        let row_count_row = &[row_count_datum];\n        let last_row_count_state = self.count_state_table.get_row(&[Datum::None; 0]).await?;\n        match last_row_count_state {\n            None => self.count_state_table.insert(row_count_row),\n            Some(last_row_count_state) => self\n                .count_state_table\n                .update(last_row_count_state, row_count_row),\n        }\n        self.count_state_table\n            .commit_assert_no_update_vnode_bitmap(epoch)","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/executor/approx_percentile/global_state.rs#L204-L240","documentation":"In `apply_row`, when a bucket's new count reaches 0 the entry should be removed from state, so `is_new_entry` must be false. If a zero new count is paired with `is_new_entry = true`, the executor would insert a nonsensical zero-count row into the bucket state table; this internal invariant violation is bailed on instead.","triggerScenarios":"Decrementing a bucket count to 0 while the entry is classified as new — a logic/state inconsistency, e.g. restored state missing an entry the code believes exists, or a bug in count bookkeeping.","commonSituations":"State restoration inconsistency after recovery, concurrency/state-write bugs, or corrupted bucket state tables causing count mismatch.","solutions":["Recreate the materialized view using approx_percentile to rebuild bucket state cleanly.","Check whether recovery/checkpoint was interrupted (previous crash) and consider re-ingesting the data.","Capture the input chunk and bucket id for a bug report; this indicates an internal invariant bug rather than a user error.","Upgrade RisingWave in case the bookkeeping bug is already fixed upstream."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat this as an internal bug: capture input chunks and report it.","Avoid interrupted recoveries; allow checkpoints to complete before shutdowns.","Recreate the affected materialized view to rebuild bucket state."],"tags":["streaming","internal-invariant","approx-percentile","state"],"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"}