{"record":{"id":"9841f7ba2367cf39","repo":"vectordotdev/vector","slug":"stack-was-empty-during-pop","errorCode":null,"errorMessage":"stack was empty during pop","messagePattern":"stack was empty during pop","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/vector-config/src/schema/visitors/inline_single.rs","lineNumber":170,"sourceCode":"        visit_schema_object_scoped(self, definitions, schema);\n\n        if let Some(current_schema_ref) = schema.reference.as_ref() {\n            let current_schema_ref = get_cleaned_schema_reference(current_schema_ref);\n            *self\n                .occurrence_map\n                .entry(current_schema_ref.into())\n                .or_default() += 1;\n        }\n    }\n}\n\nimpl ScopedVisitor for OccurrenceVisitor {\n    fn push_schema_scope<S: Into<SchemaReference>>(&mut self, scope: S) {\n        self.scope_stack.push(scope.into());\n    }\n\n    fn pop_schema_scope(&mut self) {\n        self.scope_stack.pop().expect(\"stack was empty during pop\");\n    }\n\n    fn get_current_schema_scope(&self) -> &SchemaReference {\n        self.scope_stack.current().unwrap_or(&SchemaReference::Root)\n    }\n}\n\nfn get_schema_metadata_attr<'a>(schema: &'a SchemaObject, key: &str) -> Option<&'a Value> {\n    schema\n        .extensions\n        .get(\"_metadata\")\n        .and_then(|metadata| metadata.get(key))\n}\n\n#[cfg(test)]\nmod tests {\n    use serde_json::json;\n    use vector_config_common::schema::visit::Visitor;","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/lib/vector-config/src/schema/visitors/inline_single.rs#L152-L188","documentation":"`pop_schema_scope` on `OccurrenceVisitor` pops its schema-reference scope stack and asserts a scope existed. The panic fires when pop is called without a matching push, i.e. the visitor's scope stack is empty — a tracking invariant of the scoped traversal (push on entering a $ref, pop on exit) was broken.","triggerScenarios":"Traversal code calls `pop_schema_scope` more times than `push_schema_scope` was called — e.g. a schema object without a reference still triggers a pop, or the visitor is invoked outside the standard scoped traversal driver (`visit_schema_object_scoped`).","commonSituations":"Calling visitor methods directly instead of through the scoped traversal entry point; custom schema shapes (e.g. schemas at unexpected nesting) causing unbalanced push/pop in the traversal driver.","solutions":["Only drive scoped visitors through `visit_schema_object_scoped` / the standard traversal entry points","Verify balanced push/pop pairs if you added custom traversal code","Check the schema being visited for unexpected structure and reproduce with a minimal config","Report upstream if a stock component config triggers it"],"exampleFix":"// before\nvisitor.pop_schema_scope();\nvisitor.visit_schema_object(...);\n// after\nvisitor.push_schema_scope(\"MyDef\");\nvisitor.visit_schema_object(...);\nvisitor.pop_schema_scope();","handlingStrategy":"try-catch","validationCode":"if visitor.scope_stack_is_empty() {\n    return Err(\"cannot pop schema scope: stack empty\".into());\n}","typeGuard":null,"tryCatchPattern":"match visitor.try_pop_schema_scope() {\n    Ok(scope) => scope,\n    Err(e) => { tracing::error!(\"scope pop failed: {e}\"); return Err(e); }\n}","preventionTips":["Only drive scoped visitors through visit_schema_object_scoped","Keep push/pop strictly paired in any custom traversal code","Add a debug assertion that the stack is balanced at traversal exit"],"tags":["rust","schema-generation","visitor-pattern"],"backgroundTag":"internal-invariant-violation","analyzedSha":"bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013","analyzedAt":"2026-09-16T02:53:35.741Z","contentChangedAt":"2026-09-16T02:53:35.741Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}