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

  1. Implement spawn_as_input support / an external resource for the uncovered source kind in the validation framework.
  2. Check the match in build_external_resource and add the missing source variant.
  3. 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

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


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)