vectordotdev/vector · error
Sink not present
Error message
Sink not present
What it means
During `vector validate` (or config validation at startup), healthchecks returned by topology::take_healthchecks are executed one by one; after a healthcheck future succeeds, the code looks the component back up with config.sink(&id).expect("Sink not present") to read its healthcheck.enabled setting. The expect() encodes the invariant that every healthcheck id corresponds to a configured sink. If an id has no matching sink entry, this expect panics and crashes the validate run. In released Vector the invariant holds (healthchecks are built from the config's sinks), so hitting this means an internal bug or a version skew between config parsing and topology building.
Source
Thrown at src/validate.rs:362
return !opts.deny_warnings;
}
let healthchecks = topology::take_healthchecks(diff, pieces);
// We are running health checks in serial so it's easier for the users
// to parse which errors/warnings/etc. belong to which healthcheck.
let mut validated = true;
for (id, healthcheck) in healthchecks {
let mut failed = |error| {
validated = false;
fmt.error(error);
};
trace!("Healthcheck for {id} starting.");
match tokio::spawn(healthcheck).await {
Ok(Ok(_)) => {
if config
.sink(&id)
.expect("Sink not present")
.healthcheck()
.enabled
{
fmt.success(format!("Health check \"{id}\""));
} else {
fmt.warning(format!("Health check disabled for \"{id}\""));
validated &= !opts.deny_warnings;
}
}
Ok(Err(e)) => failed(format!("Health check for \"{id}\" failed: {e}")),
Err(error) if error.is_cancelled() => {
failed(format!("Health check for \"{id}\" was cancelled"))
}
Err(_) => failed(format!("Health check for \"{id}\" panicked")),
}
trace!("Healthcheck for {id} done.");
}
View on GitHub (pinned to 3708c39b12)
Solutions
- Rerun with `vector validate --skip-healthchecks` (or set healthchecks.enabled = false in the config) to bypass the panicking path and validate the rest of the config.
- Check for version mismatch: make sure the `vector` binary executing validate is the version you think (vector --version) and re-run with the matching binary.
- If you run a fork/patched Vector, audit topology::take_healthchecks to confirm it only yields ids that exist in config.sinks, and file an issue upstream with the config and panic backtrace.
- Report the panic to the Vector maintainers with your config (redacted) and backtrace — stock builds should never hit this.
Example fix
// before (src/validate.rs:360-365)
if config.sink(&id).expect("Sink not present").healthcheck().enabled {
fmt.success(format!("Health check \"{id}\""));
}
// after — degrade gracefully instead of panicking the validator
match config.sink(&id) {
Some(sink) if sink.healthcheck().enabled => {
fmt.success(format!("Health check \"{id}\""));
}
Some(_) => {
fmt.warning(format!("Health check disabled for \"{id}\""));
validated &= !opts.deny_warnings;
}
None => failed(format!("Health check for \"{id}\" has no matching sink")),
} Defensive patterns
Strategy: validation
Validate before calling
# Avoid the panicking healthcheck path entirely when validating config files vector validate --skip-healthchecks /etc/vector/vector.yaml # Or disable healthchecks in the config before validating grep -q '^healthchecks:' config.yaml || printf '\nhealthchecks:\n enabled: false\n' >> config.yaml
Prevention
- Run `vector validate --skip-healthchecks` in CI for pure config-shape checks; only run full healthchecks against throwaway environments.
- Verify binary/config version alignment (vector --version vs. config features) before validating configs produced for a different Vector release.
- If you embed vector-lib or fork topology code, add a unit test asserting every id from take_healthchecks exists in config.sinks.
When it happens
Trigger: Running `vector validate` (without --skip-healthchecks) against a config, and a healthcheck id returned by take_healthchecks does not resolve via config.sink(&id). This can only happen if healthchecks were taken for non-sink components or the config object was mutated between building pieces and validating — e.g., a bug in a custom build of Vector, a patched topology module, or source-provided healthchecks not filtered out.
Common situations: Custom forks/embedded Vector-lib where topology::take_healthchecks is extended; running `vector validate` on a config after a partial code upgrade (binary version newer/older than expected config semantics); otherwise virtually unreachable for stock configs — normal bad configs produce 'Health check for X failed' messages instead of this panic.
Related errors
- Invalid cache settings: {e:?}
- MessageStream never calls Ready(None)
- MessageStream never returns Ready(None)
- Messages are consumed in dedicated tasks for each partition.
- Indexer acknowledgements channel must allow at least one pen
AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20).
Data as JSON: /api/errors/dbaec1f5f982c42d.
Report an issue: GitHub.