vectordotdev/vector · error

schema reference should exist

Error message

schema reference should exist

What it means

`visit_schema_object_scoped` resolves a schema object's `$ref` against the root definitions map, clones it, and asserts it exists before recursively visiting it under a new scope. The panic fires when the referenced definition name is not present in `definitions`, meaning a reference points to a definition that was removed or never registered.

Solutions

  1. Validate that every `$ref` in the root schema resolves to an entry in `definitions` before running the visitor pipeline
  2. Keep the visitor that removes definitions ordered after all ref-resolving visitors
  3. Check `Cargo.lock` for a schemars version mismatch after dependency upgrades
  4. Reproduce with a minimal schema and log the definitions map at visitor entry

Example fix

// before
if !schema.definitions.contains_key("MyDef") { schema.definitions.remove("Other"); }
visitor.visit_root_schema(&mut schema);
// after
visitor.visit_root_schema(&mut schema); // let ref-resolving visitors run before any removal
Defensive patterns

Strategy: validation

Validate before calling

fn all_refs_resolve(root: &RootSchema) -> Result<(), String> {
    fn walk(s: &Schema, defs: &Map<String, Schema>) -> Result<(), String> {
        if let Schema::Object(o) = s {
            if let Some(r) = &o.reference {
                let key = r.trim_start_matches("#/definitions/");
                if !defs.contains_key(key) { return Err(format!("unresolved $ref: {key}")); }
            }
            if let Some(sub) = &o.subschemas {
                for child in sub.iter_children() { walk(child, defs)?; }
            }
            if let Some(obj) = &o.object {
                for p in obj.properties.values() { walk(p, defs)?; }
            }
        }
        Ok(())
    }
    if let Some(sub) = &root.schema.subschemas {
        for child in sub.iter_children() { walk(child, &root.definitions)?; }
    }
    Ok(())
}

Type guard

fn resolve_ref<'a>(defs: &'a Map<String, Schema>, reference: &str) -> Option<&'a Schema> {
    defs.get(get_cleaned_schema_reference(reference))
}

Try / catch

let referenced = definitions.get(schema_def_key).cloned().ok_or_else(||
    anyhow::anyhow!("$ref {schema_def_key} does not resolve in definitions"))?;

Prevention

When it happens

Trigger: Visiting a schema whose `$ref` target is missing from `root.definitions` — definitions pruned by an earlier visitor, a hand-assembled `RootSchema`, or a schemars version emitting `$ref`s to external/absent definitions.

Common situations: Composing visitors where one deletes definitions another still needs; constructing schemas programmatically with stale `$ref` strings; upgrading schemars and relying on renamed definition keys.

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/99fbc9ab0d7bb5e8. Report an issue: GitHub.

Appendix: source

Thrown at lib/vector-config/src/schema/visitors/scoped_visit.rs:85

pub trait ScopedVisitor: Visitor {
    fn push_schema_scope<S: Into<SchemaReference>>(&mut self, scope: S);

    fn pop_schema_scope(&mut self);

    fn get_current_schema_scope(&self) -> &SchemaReference;
}

pub fn visit_schema_object_scoped<SV: ScopedVisitor + ?Sized>(
    sv: &mut SV,
    definitions: &mut Map<String, Schema>,
    schema: &mut SchemaObject,
) {
    if let Some(reference) = schema.reference.as_ref() {
        let schema_def_key = get_cleaned_schema_reference(reference);
        let mut referenced_schema = definitions
            .get(schema_def_key)
            .cloned()
            .expect("schema reference should exist");

        if let Schema::Object(referenced_schema) = &mut referenced_schema {
            sv.push_schema_scope(schema_def_key);

            sv.visit_schema_object(definitions, referenced_schema);

            sv.pop_schema_scope();
        }

        definitions.insert(schema_def_key.to_string(), referenced_schema);
    }

    if let Some(sub) = &mut schema.subschemas {
        visit_vec_scoped(sv, definitions, &mut sub.all_of);
        visit_vec_scoped(sv, definitions, &mut sub.any_of);
        visit_vec_scoped(sv, definitions, &mut sub.one_of);
        visit_box_scoped(sv, definitions, &mut sub.not);
        visit_box_scoped(sv, definitions, &mut sub.if_schema);

View on GitHub (pinned to bdb87aeaa4)