risingwavelabs/risingwave · error · anyhow

take receiver on unmatched partial graph term to current…

Error message

take receiver {:?} on unmatched partial graph term {} to current term {}

What it means

An actor sent a TakeReceiver (exchange channel creation) request whose term (epoch) id does not match the term id of the currently running partial graph. The barrier worker rejects the request and reports the error back to the remote sender via the result_sender. It protects the graph from wiring exchange channels across generation boundaries.

Solutions

  1. Retry the TakeReceiver request with the current term id after the graph reset completes.
  2. Check logs for a preceding partial graph reset that changed the term id.
  3. Verify upstream/downstream term id propagation in the streaming control requests.
  4. If persistent, inspect barrier scheduling for term regression across meta and compute nodes.

Example fix

// before: taking receiver with stale term
worker.take_receiver(partial_graph_id, stale_term_id, ids, request);
// after: ensure request carries the term id observed from the latest barrier
let term_id = graph.local_barrier_manager.term_id;
worker.take_receiver(partial_graph_id, term_id, ids, request);
Defensive patterns

Strategy: retry

Validate before calling

// caller-side check before sending TakeReceiver
if request.term_id != current_graph_term_id(partial_graph_id) {
    refresh_term_id_before_take_receiver();
}

Type guard

fn is_term_mismatch(err: &anyhow::Error) -> bool { err.to_string().contains("unmatched partial graph term") }

Try / catch

// treat rejection as retryable
if let Err(e) = sender.await_reply() {
    if is_term_mismatch(&e) { fetch_new_term_id().await; retry_take_receiver().await; }
}

Prevention

When it happens

Trigger: handle_actor_op receives LocalActorOperation::TakeReceiver while the partial graph is PartialGraphStatus::Running and graph.local_barrier_manager.term_id != term_id.

Common situations: A slow upstream actor's exchange request races with a barrier-driven graph rebuild; a partial graph reset occurred between the request being issued and processed; config/planner changes causing frequent term bumps under failure recovery.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/stream/src/task/barrier_worker/mod.rs:535

                ids,
                request,
            } => {
                let err = match self.state.partial_graphs.entry(partial_graph_id) {
                    Entry::Occupied(mut entry) => match entry.get_mut() {
                        PartialGraphStatus::ReceivedExchangeRequest(pending_requests) => {
                            pending_requests.push((term_id, ids, request));
                            return;
                        }
                        PartialGraphStatus::Running(graph) => {
                            if graph.local_barrier_manager.term_id != term_id {
                                warn!(
                                    %partial_graph_id,
                                    ?ids,
                                    request_term_id = term_id,
                                    current_term_id = graph.local_barrier_manager.term_id,
                                    "take receiver on unmatched partial graph term"
                                );
                                anyhow!(
                                    "take receiver {:?} on unmatched partial graph term {} to current term {}",
                                    ids,
                                    term_id,
                                    graph.local_barrier_manager.term_id
                                )
                            } else {
                                let (upstream_actor_id, actor_id) = ids;
                                graph.new_actor_output_request(
                                    actor_id,
                                    upstream_actor_id,
                                    request,
                                );
                                return;
                            }
                        }
                        PartialGraphStatus::Suspended(_) => anyhow!("partial graph suspended"),
                        PartialGraphStatus::Resetting => anyhow!("partial graph resetting"),
                        PartialGraphStatus::Unspecified => unreachable!(),

View on GitHub (pinned to 6469eb736d)