{"record":{"id":"5893da9c9cf1483b","repo":"vectordotdev/vector","slug":"transform-must-exist-already-found-inputs","errorCode":null,"errorMessage":"transform must exist - already found inputs","messagePattern":"transform must exist - already found inputs","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/topology/schema.rs","lineNumber":74,"sourceCode":"            }\n\n            definitions.append(&mut source_definition);\n        }\n\n        // If the input is a transform, the output is merged into the top-level schema\n        if let Some(inputs) = config.transform_inputs(key) {\n            let input_definitions =\n                possible_definitions(inputs, config, enrichment_tables.clone(), cache)?;\n\n            let mut transform_definition = input.with_definitions(\n                config\n                    .transform_output_for_port(\n                        key,\n                        &input.port,\n                        enrichment_tables.clone(),\n                        &input_definitions,\n                    )\n                    .expect(\"transform must exist - already found inputs\")\n                    .unwrap_or_else(|| {\n                        unreachable!(\n                            \"transform output misconfigured - output for port {:?} missing\",\n                            &input.port\n                        )\n                    })\n                    .schema_definitions(config.schema_enabled())\n                    .values()\n                    .cloned(),\n            );\n\n            if contains_never(&transform_definition) {\n                return Err(Error::ContainsNever);\n            }\n\n            definitions.append(&mut transform_definition);\n        }\n    }","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/src/topology/schema.rs#L56-L92","documentation":"In `possible_definitions` (src/topology/schema.rs:74), the code resolves each transform via `transform_output_for_port(...).expect(\"transform must exist - already found inputs\")`. The invariant is that inputs were enumerated in a previous pass, so the transform must exist in the config; a None means the schema-resolution cache/iteration found inputs for a transform that no longer resolves.","triggerScenarios":"Schema definition resolution encountering a transform key whose inputs were found but whose transform definition is absent — usually from inconsistent config iteration or a recursive call with a stale/partial config.","commonSituations":"Topology validation of hand-built Config objects in tests; config with references to transforms removed mid-resolution; custom tooling that mutates Config between passes.","solutions":["Ensure the Config is immutable and consistent while schema definitions are being computed.","Verify every transform referenced in `inputs` has a corresponding transform entry in the config.","Rebuild the config from a single parse rather than mutating it programmatically."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// every transform referenced by inputs must exist in config.transforms\nfor t in &config.transforms {\n    for inp in &t.inputs { assert!(config.transform_inputs(inp).is_some(), \"missing transform {inp}\"); }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not mutate Config between schema resolution passes.","Generate configs with the standard parser; avoid hand-assembled fragments.","Keep transform names consistent between definition and references."],"tags":["rust","schema","topology","panic"],"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"}