vectordotdev/vector · critical

Pausing unknown sink from fanout: {id}

Error message

Pausing unknown sink from fanout: {id}

What it means

Handling ControlMessage::Pause, Fanout::pause() looks up the sink by ComponentKey and panics when the key is absent. Pausing is only valid for a sink the fanout knows: the topology pauses a sink (taking its sender) right before replacing it during a rebuild. An unknown key means the control protocol was violated - pausing something that was never added or was already removed.

Source

Thrown at lib/vector-core/src/fanout.rs:112

                    sender.replace(Sender::new(sink)).is_none(),
                    "Replacing existing sink is not valid: {id}"
                );
            }
            None => panic!("Replacing unknown sink from fanout: {id}"),
        }
    }

    fn pause(&mut self, id: &ComponentKey) {
        match self.senders.get_mut(id) {
            Some(sender) => {
                // A sink must be known and present to be replaced, otherwise an invalid sequence of
                // control operations has been applied.
                assert!(
                    sender.take().is_some(),
                    "Pausing nonexistent sink is not valid: {id}"
                );
            }
            None => panic!("Pausing unknown sink from fanout: {id}"),
        }
    }

    /// Waits for the next control message and applies it.
    ///
    /// Returns `true` if a message was processed, `false` if the control
    /// channel was closed.
    pub async fn recv_control_message(&mut self) -> bool {
        match self.control_channel.recv().await {
            Some(msg) => {
                self.apply_control_message(msg);
                true
            }
            None => false,
        }
    }

    /// Apply a control message directly against this instance.

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Upgrade Vector - pause/replace sequencing bugs in the fanout have been fixed upstream; verify against the release changelog
  2. If it reproduces, file an issue with the reload sequence (before/after configs) and debug logs of ControlMessage traffic
  3. Avoid reloading configs that simultaneously remove and re-add the same sink id; restart instead
  4. For embedders: track added ids and emit at most one Pause per id, strictly between its Add and its Remove/Replace
Defensive patterns

Strategy: validation

Validate before calling

// Before pausing, confirm the sink is still registered in your orchestration view
// and that you have not already sent Remove for it:
if registered.contains(&id) && !removed.contains(&id) {
    control_tx.send(ControlMessage::Pause(id));
}

Prevention

When it happens

Trigger: A ControlMessage::Pause(id) processed after ControlMessage::Remove(id), or for an id that never had a successful Add; the None arm of senders.get_mut(id) is hit and the panic fires. Occurs mid-reload when sink sets are computed inconsistently.

Common situations: Config reloads that remove and re-add sinks in one operation on older Vector builds; unit tests of topology rebuilding that exercise pause/replace with stale ids; custom orchestrators wrapping Vector's topology API and emitting duplicate Pause messages.

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 vectordotdev/vector@3708c39b12 (2026-08-20). Data as JSON: /api/errors/fa1696b693c30a89. Report an issue: GitHub.