vectordotdev/vector · error

schema definition must exist

Error message

schema definition must exist

What it means

While collecting definitions eligible for inlining, `visit_root_schema` looks up each candidate `$ref` name in the root schema's `definitions` map and asserts it exists. The panic fires when a definition name appears in the inline-candidate list but is missing from `root.definitions`, meaning the root schema's definitions were mutated or built inconsistently.

Solutions

  1. Ensure visitors that mutate `definitions` run in the intended order (inline_single's own visiting before any removal-based visitor)
  2. Check that no other code drains/moves `root.definitions` before `visit_root_schema`
  3. Pin consistent versions of vector-config-related crates in the workspace
  4. Reproduce with a minimal `RootSchema` and add debug logging of definition names

Example fix

// before (wrong order)
schema_pipeline.push(RemovingVisitor::default());
schema_pipeline.push(InlineSingleVisitor::default());
// after
schema_pipeline.push(InlineSingleVisitor::default());
schema_pipeline.push(RemovingVisitor::default());
Defensive patterns

Strategy: validation

Validate before calling

fn validate_refs_resolve(root: &RootSchema) -> Result<(), String> {
    for name in root.definitions.keys() {
        if !root.definitions.contains_key(name) {
            return Err(format!("dangling schema definition: {name}"));
        }
    }
    Ok(())
}

Type guard

fn definition_exists<'a>(root: &'a RootSchema, name: &str) -> Option<&'a Schema> { root.definitions.get(name) }

Try / catch

let schema = root.definitions.get(def_name.as_ref()).ok_or_else(||
    anyhow::anyhow!("schema definition {def_name:?} missing from root definitions"))?;

Prevention

When it happens

Trigger: Calling `visit_root_schema` on a `RootSchema` whose `definitions` map lacks an entry referenced by an earlier enumeration pass — e.g. the definitions were moved/drained before this visitor runs, or a composed visitor pipeline mutated definitions out of order.

Common situations: Chaining schema visitors in a non-standard order (running inline_single after another visitor that removes definitions); version skew between vector-config crates that changed visitor ordering.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/75d0808e3d5c8e55. Report an issue: GitHub.

Appendix: source

Thrown at lib/vector-config/src/schema/visitors/inline_single.rs:61

        let occurrence_map = occurrence_visitor.occurrence_map;

        self.eligible_to_inline = occurrence_map
            .into_iter()
            // Filter out any schemas which have more than one occurrence, as naturally, we're
            // trying to inline single-use schema references. :)
            .filter_map(|(def_name, occurrences)| (occurrences == 1).then_some(def_name))
            // However, we'll also filter out some specific schema definitions which are only
            // referenced once, specifically: component base types and component types themselves.
            //
            // We do this as a lot of the tooling that parses the schema to generate documentation,
            // and the like, depends on these schemas existing in the top-level definitions for easy
            // lookup.
            .filter(|def_name| {
                let schema = root
                    .definitions
                    .get(def_name.as_ref())
                    .and_then(Schema::as_object)
                    .expect("schema definition must exist");

                is_inlineable_schema(def_name.as_ref(), schema)
            })
            .map(|s| s.as_ref().to_string())
            .collect::<HashSet<_>>();

        // Now run our own visitor logic, which will use the inline eligibility to determine if a
        // schema reference in a being-visited schema should be replaced inline with the original
        // referenced schema, in turn removing the schema definition.
        visit::visit_root_schema(self, root);

        // Now remove all of the definitions for schemas that were eligible for inlining.
        for schema_def_name in self.eligible_to_inline.drain() {
            debug!(
                referent = schema_def_name,
                "Removing schema definition from root schema."
            );

View on GitHub (pinned to bdb87aeaa4)