vectordotdev/vector · error
a source must always have an external resource
Error message
a source must always have an external resource
What it means
build_external_resource requires that every source under validation has an associated external resource; otherwise there is nowhere to deliver input events. The expect fires when the source type did not produce an external resource earlier in the construction, meaning the validation framework's coverage of source kinds is incomplete (a code bug, not a user config error).
Solutions
- Implement spawn_as_input support / an external resource for the uncovered source kind in the validation framework.
- Check the match in build_external_resource and add the missing source variant.
- Return a descriptive error naming the source type instead of a bare expect.
Example fix
// before
let resource = maybe_external_resource.expect("a source must always have an external resource");
// after
let resource = maybe_external_resource
.unwrap_or_else(|| panic!("source kind {:?} has no external resource support", source_type)); Defensive patterns
Strategy: validation
Validate before calling
// Before running validation, confirm the source kind is supported
assert!(matches!(source, SourceConfig::File(_) | SourceConfig::Socket(_) /* ... */),
"source kind lacks external-resource support"); Try / catch
let resource = maybe_external_resource.unwrap_or_else(||
panic!("no external resource implemented for this source kind")); Prevention
- Add external-resource support for every new source type before enabling validation.
- Keep the build_external_resource match exhaustive with a compile-time-checked enum.
- Name the offending source type in the panic message for faster triage.
When it happens
Trigger: run_validation calls build_external_resource for a source whose maybe_external_resource is None — i.e. a source kind not handled by the match that spawns channel/socket-based resources.
Common situations: Adding a new source type and running validation before implementing its external-resource support; a refactored match arm that silently skips a source variant.
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
- argument must be a string
- argument must be a string
- argument must be a string
- argument must be a string
- argument must be a string
AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16).
Data as JSON: /api/errors/03be0d9e06851dd2.
Report an issue: GitHub.
Appendix: source
Thrown at src/components/validation/runner/mod.rs:470
) -> Result<(RunnerInput, RunnerOutput, Option<Encoder<encoding::Framer>>), vector_lib::Error> {
let component_type = configuration.component_type();
let maybe_external_resource = configuration.external_resource(test_case.config_name.as_ref());
let resource_codec = maybe_external_resource
.as_ref()
.map(|resource| resource.codec.clone());
let maybe_encoder = resource_codec.as_ref().map(|codec| codec.into_encoder());
match component_type {
ComponentType::Source => {
// As an external resource for a source, we create a channel that the validation runner
// uses to send the input events to the external resource. We don't care if the source
// pulls those input events or has them pushed in: we just care about getting them to
// the external resource.
let (tx, rx) = mpsc::channel(1024);
let resource =
maybe_external_resource.expect("a source must always have an external resource");
resource.spawn_as_input(rx, input_task_coordinator, runner_metrics);
Ok((
RunnerInput::External(tx),
RunnerOutput::Controlled,
maybe_encoder,
))
}
ComponentType::Transform => {
// Transforms have no external resources.
Ok((RunnerInput::Controlled, RunnerOutput::Controlled, None))
}
ComponentType::Sink => {
// As an external resource for a sink, we create a channel that the validation runner
// uses to collect the output events from the external resource. We don't care if the sink
// pushes those output events to the external resource, or if the external resource
// pulls them from the sink: we just care about getting them from the external resource.
let (tx, rx) = mpsc::channel(1024);View on GitHub (pinned to bdb87aeaa4)