{"record":{"id":"33e7cce461f40f0e","repo":"risingwavelabs/risingwave","slug":"fragment-missing-in-shared-actor-info-map","errorCode":null,"errorMessage":"fragment {} missing in shared actor info map","messagePattern":"fragment (.+?) missing in shared actor info map","errorType":"exception","errorClass":"MetaError","httpStatus":null,"severity":"warning","filePath":"src/meta/src/controller/fragment.rs","lineNumber":1049,"sourceCode":"\n            actor_map.insert(*fragment_id, actors);\n        }\n\n        Ok(actor_map)\n    }\n\n    fn collect_fragment_actor_pairs(\n        &self,\n        fragments: Vec<fragment::Model>,\n        stream_context: StreamContext,\n    ) -> MetaResult<Vec<(fragment::Model, Vec<ActorInfo>)>> {\n        let fragment_ids: Vec<_> = fragments.iter().map(|f| f.fragment_id).collect();\n        let mut actor_map = self.collect_fragment_actor_map(&fragment_ids, stream_context)?;\n        fragments\n            .into_iter()\n            .map(|fragment| {\n                let actors = actor_map.remove(&fragment.fragment_id).ok_or_else(|| {\n                    anyhow!(\n                        \"fragment {} missing in shared actor info map\",\n                        fragment.fragment_id\n                    )\n                })?;\n                Ok((fragment, actors))\n            })\n            .collect()\n    }\n\n    // TODO: This function is too heavy, we should avoid using it and implement others on demand.\n    pub async fn table_fragments(\n        &self,\n    ) -> MetaResult<\n        BTreeMap<\n            JobId,\n            (\n                StreamJobFragments,\n                HashMap<FragmentId, Vec<StreamActor>>,","sourceCodeStart":1031,"sourceCodeEnd":1067,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/meta/src/controller/fragment.rs#L1031-L1067","documentation":"collect_fragment_actor_pairs first collects an actor map keyed by fragment id, then removes one entry per fragment; if the map lacks the key during removal it returns 'fragment {} missing in shared actor info map'. This is a defensive consistency check mirroring the lookup done in collect_fragment_actor_map — normally unreachable unless actor collection returned an incomplete/empty map.","triggerScenarios":"Calling get_job_fragments_by_id or table_fragments when collect_fragment_actor_map silently returns a map missing an entry for one of the fragments (e.g. empty fragment_ids list handling or an internal code change to the collection logic).","commonSituations":"Primarily seen during internal development/refactoring of fragment actor collection; extremely rare in production because the preceding map lookup already fails for missing fragments.","solutions":["Inspect collect_fragment_actor_map to ensure every requested fragment id yields a map entry","Confirm fragment_ids are derived from the same fragments list used for removal","Add unit coverage in src/meta/src/controller/fragment.rs tests (compose_fragment module) for the affected path"],"exampleFix":"// before\nlet actors = actor_map.remove(&fragment.fragment_id).ok_or_else(|| anyhow!(\"fragment {} missing\", fragment.fragment_id))?;\n// after\nlet actors = actor_map.remove(&fragment.fragment_id)\n    .ok_or_else(|| MetaError::internal(format!(\"fragment {} missing in actor map\", fragment.fragment_id)))?;","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn map_has_all(map: &HashMap<FragmentId, Vec<ActorInfo>>, ids: &[FragmentId]) -> bool { ids.iter().all(|id| map.contains_key(id)) }","tryCatchPattern":"let actors = match actor_map.remove(&fragment.fragment_id) { Some(a) => a, None => return Err(internal_error(...)) };","preventionTips":["Keep fragment id derivation and map removal on the same list","Add unit tests covering empty and partial actor maps","Prefer typed internal errors for unreachable paths"],"tags":["internal-invariant","fragment","map-lookup"],"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"}