risingwavelabs/risingwave · warning · MetaError

fragment {} missing in shared actor info map

Error message

fragment {} missing in shared actor info map

What it means

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.

Source

Thrown at src/meta/src/controller/fragment.rs:1049

            actor_map.insert(*fragment_id, actors);
        }

        Ok(actor_map)
    }

    fn collect_fragment_actor_pairs(
        &self,
        fragments: Vec<fragment::Model>,
        stream_context: StreamContext,
    ) -> MetaResult<Vec<(fragment::Model, Vec<ActorInfo>)>> {
        let fragment_ids: Vec<_> = fragments.iter().map(|f| f.fragment_id).collect();
        let mut actor_map = self.collect_fragment_actor_map(&fragment_ids, stream_context)?;
        fragments
            .into_iter()
            .map(|fragment| {
                let actors = actor_map.remove(&fragment.fragment_id).ok_or_else(|| {
                    anyhow!(
                        "fragment {} missing in shared actor info map",
                        fragment.fragment_id
                    )
                })?;
                Ok((fragment, actors))
            })
            .collect()
    }

    // TODO: This function is too heavy, we should avoid using it and implement others on demand.
    pub async fn table_fragments(
        &self,
    ) -> MetaResult<
        BTreeMap<
            JobId,
            (
                StreamJobFragments,
                HashMap<FragmentId, Vec<StreamActor>>,

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect collect_fragment_actor_map to ensure every requested fragment id yields a map entry
  2. Confirm fragment_ids are derived from the same fragments list used for removal
  3. Add unit coverage in src/meta/src/controller/fragment.rs tests (compose_fragment module) for the affected path

Example fix

// before
let actors = actor_map.remove(&fragment.fragment_id).ok_or_else(|| anyhow!("fragment {} missing", fragment.fragment_id))?;
// after
let actors = actor_map.remove(&fragment.fragment_id)
    .ok_or_else(|| MetaError::internal(format!("fragment {} missing in actor map", fragment.fragment_id)))?;
Defensive patterns

Strategy: type-guard

Type guard

fn map_has_all(map: &HashMap<FragmentId, Vec<ActorInfo>>, ids: &[FragmentId]) -> bool { ids.iter().all(|id| map.contains_key(id)) }

Try / catch

let actors = match actor_map.remove(&fragment.fragment_id) { Some(a) => a, None => return Err(internal_error(...)) };

Prevention

When it happens

Trigger: 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).

Common situations: Primarily seen during internal development/refactoring of fragment actor collection; extremely rare in production because the preceding map lookup already fails for missing fragments.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/33e7cce461f40f0e. Report an issue: GitHub.