vectordotdev/vector · error
Couldn't broadcast config changes.
Error message
Couldn't broadcast config changes.
What it means
`connect_diff` broadcasts a config-change diff over a broadcast channel and panics via `.expect("Couldn't broadcast config changes.")` if the send fails (src/topology/running.rs:936). With tokio broadcast channels, send only fails when there are no live receivers. Since topology reload expects its control-plane receivers to be alive, failure means the watching tasks have all exited.
Solutions
- Ensure the topology's control receivers (handle watchers) outlive any reload attempt before calling reload.
- Serialize reload against shutdown so connect_diff does not run during teardown.
- Recreate the running topology instead of reloading if its watchers are known dead.
Defensive patterns
Strategy: retry
Validate before calling
if watchers_alive(&topology.handles) { topology.connect_diff(diff).await; } Try / catch
// tokio broadcast send failure = no receivers; detect via receiver count before reload
if topology.handles.receiver_count() == 0 { log::error!("watchers gone; cannot reload"); return; } Prevention
- Hold the control-channel receivers for the lifetime of the running topology.
- Serialize reloads against shutdown with a shutdown token/flag.
- Prefer full restart over reload if watcher health is uncertain.
When it happens
Trigger: Calling `reload_config_and_respawn` -> `connect_diff` after the diff-broadcast receiver tasks (e.g. handle-based watchers) have been dropped or shut down.
Common situations: A topology reload issued after the API/handle subscribers died; application shutting down while a reload races through connect_diff.
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
- Pausing unknown sink from fanout
- Replacing unknown sink from fanout
- unknown output
- can't run runner twice
- join error or bad poll
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/1c7f8e9e9745093b.
Report an issue: GitHub.
Appendix: source
Thrown at src/topology/running.rs:936
.map(|key| key.to_string()),
)
.collect(),
sink_keys: diff
.sinks
.changed_and_added()
.map(|key| key.to_string())
.chain(added_changed_tables.iter().map(|key| key.to_string()))
.collect(),
// Note, only sources and transforms are relevant. Sinks do
// not have outputs to tap.
removals,
type_names: self
.component_type_names
.iter()
.map(|(k, v)| (k.to_string(), v.clone()))
.collect(),
})
.expect("Couldn't broadcast config changes.");
}
}
fn setup_outputs(&mut self, key: &ComponentKey, new_pieces: &mut builder::TopologyPieces) {
let outputs = new_pieces.outputs.remove(key).unwrap();
for (port, output) in outputs {
debug!(component_id = %key, output_id = ?port, "Configuring output for component.");
let id = OutputId {
component: key.clone(),
port,
};
self.outputs.insert(id, output);
}
}
fn setup_inputs(View on GitHub (pinned to bdb87aeaa4)