{"record":{"id":"7064b33230bb6e03","repo":"risingwavelabs/risingwave","slug":"not-yet-implemented-is-dirty","errorCode":null,"errorMessage":"not yet implemented: is_dirty","messagePattern":"not yet implemented: is_dirty","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/stream/src/executor/hash_join.rs","lineNumber":137,"sourceCode":"    _marker: std::marker::PhantomData<E>,\n}\n\nimpl<K: HashKey, S: StateStore, E: JoinEncoding> std::fmt::Debug for JoinSide<K, S, E> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.debug_struct(\"JoinSide\")\n            .field(\"join_key_indices\", &self.join_key_indices)\n            .field(\"col_types\", &self.all_data_types)\n            .field(\"start_pos\", &self.start_pos)\n            .field(\"i2o_mapping\", &self.i2o_mapping)\n            .field(\"need_degree_table\", &self.need_degree_table)\n            .finish()\n    }\n}\n\nimpl<K: HashKey, S: StateStore, E: JoinEncoding> JoinSide<K, S, E> {\n    // WARNING: Please do not call this until we implement it.\n    fn is_dirty(&self) -> bool {\n        unimplemented!()\n    }\n\n    #[expect(dead_code)]\n    fn clear_cache(&mut self) {\n        assert!(\n            !self.is_dirty(),\n            \"cannot clear cache while states of hash join are dirty\"\n        );\n\n        // TODO: not working with rearranged chain\n        // self.ht.clear();\n    }\n\n    pub async fn init(&mut self, epoch: EpochPair) -> StreamExecutorResult<()> {\n        self.ht.init(epoch).await\n    }\n}\n","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/executor/hash_join.rs#L119-L155","documentation":"`JoinSide::is_dirty` in the hash join executor is a deliberate `unimplemented!()` stub, guarded by a comment warning not to call it until implemented. Panics with \"not yet implemented: is_dirty\" whenever invoked. Currently only reachable from `clear_cache`, which is itself `#[expect(dead_code)]`.","triggerScenarios":"Any code path calling `JoinSide::is_dirty` on a hash-join side — today only the (dead) `clear_cache` method at src/stream/src/executor/hash_join.rs:137; enabling that code path or adding new cache-eviction logic that checks dirtiness.","commonSituations":"Contributors wiring up join cache clearing or memory management who un-comment/call the guarded method; new tooling or metrics code probing join cache state.","solutions":["Do not call `is_dirty` until it is implemented (see the WARNING comment above it).","Implement `is_dirty` for `JoinSide` (e.g. return whether the degree table/cache has entries) before using it.","If you need cache clearing, implement a check that does not rely on `is_dirty`, or remove the `#[expect(dead_code)]` only after both methods work."],"exampleFix":"// before\nfn is_dirty(&self) -> bool {\n    unimplemented!()\n}\n// after\nfn is_dirty(&self) -> bool {\n    !self.degree_table.is_empty()\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// The method always panics; only safe pattern is to avoid calling it.\n// Until implemented, gate call sites:\n// debug_assert!(false, \"do not call JoinSide::is_dirty until implemented\");\n// or feature-gate the caller entirely.","preventionTips":["Respect the WARNING comment above the method: do not call it.","If you need dirtiness info, implement is_dirty first and add tests.","Keep clear_cache dead-code-gated until is_dirty exists."],"tags":["stream-executor","hash-join","unimplemented","panic"],"backgroundTag":"method-not-implemented","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}