{"record":{"id":"0aca3da9334a5410","repo":"risingwavelabs/risingwave","slug":"failed-to-receive-update-vnode","errorCode":null,"errorMessage":"failed to receive update vnode","messagePattern":"failed to receive update vnode","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/stream/src/common/log_store_impl/kv_log_store/reader.rs","lineNumber":341,"sourceCode":"\n    async fn init(&mut self) -> LogStoreResult<()> {\n        if let Some(init_epoch_rx) = self.init_epoch_rx.take() {\n            let init_epoch = init_epoch_rx\n                .await\n                .map_err(|_| anyhow!(\"should get the first epoch\"))?;\n            let first_write_epoch = init_epoch.curr;\n\n            assert_eq!(\n                self.first_write_epoch.replace(first_write_epoch),\n                None,\n                \"should not init twice\"\n            );\n        } else {\n            let (new_vnode_bitmap, write_epoch) = self\n                .update_vnode_bitmap_rx\n                .recv()\n                .await\n                .ok_or_else(|| anyhow!(\"failed to receive update vnode\"))?;\n            self.state.serde.update_vnode_bitmap(new_vnode_bitmap);\n            self.first_write_epoch = Some(write_epoch);\n        };\n\n        self.future_state = KvLogStoreReaderFutureState::Reset;\n        self.latest_offset = None;\n        self.truncate_offset = None;\n        self.rewind_delay = RewindDelay::new(&self.metrics);\n\n        Ok(())\n    }\n\n    async fn next_item(&mut self) -> LogStoreResult<(u64, LogStoreReadItem)> {\n        while *self.is_paused.borrow_and_update() {\n            info!(\"next_item of {} get blocked by is_pause\", self.identity);\n            self.is_paused\n                .changed()\n                .instrument_await(\"Wait for Pause Resume\")","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/common/log_store_impl/kv_log_store/reader.rs#L323-L359","documentation":"This is the other branch of KvLogStoreReader::init: when the reader has no init-epoch oneshot, it instead expects the first message on `update_vnode_bitmap_rx` to carry a new vnode bitmap and write epoch. Receiving None means all senders of that channel were dropped, so the reader never learned its vnode mapping and cannot initialize its deserializer/epoch baseline.","triggerScenarios":"Reader init without an init_epoch_rx, but the component that sends the vnode bitmap update (the upstream executor / merge owner) dropped its sender before delivering the bitmap — e.g. it terminated or was reconfigured away.","commonSituations":"Upstream executor failure during reader initialization; scaling/migration paths where the vnode update sender is replaced but the old reader persists; ordering bugs where reader init runs after upstream teardown.","solutions":["Check why the vnode-bitmap sender side terminated before sending (upstream actor logs).","Ensure reader init happens only while the vnode-update sender is alive and running.","Verify the correct init mode: either a writer oneshot or a live vnode-bitmap channel must exist.","Treat as terminal for the reader and rebuild it through recovery."],"exampleFix":"// before: reader initialized after upstream dropped the vnode channel\ndrop(vnode_update_tx);\nreader.init().await?;\n\n// after: keep sender alive until reader init completes\nreader.init().await?;\ndrop(vnode_update_tx);","handlingStrategy":"try-catch","validationCode":"if vnode_update_tx.is_closed() {\n    fail_fast(\"vnode update sender gone before reader init\");\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = reader.init().await {\n    if e.to_string().contains(\"failed to receive update vnode\") {\n        // upstream dropped the bitmap channel; rebuild reader via recovery\n        rebuild_reader();\n    }\n    return Err(e);\n}","preventionTips":["Keep the vnode-bitmap sender alive until reader init completes.","Initialize the reader while its upstream executor is still running.","Pick exactly one init mode (writer oneshot or vnode channel) consistently."],"tags":["channel-closed","vnode","init","log-store"],"backgroundTag":"broken-pipe","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"}