{"record":{"id":"2b296b0a5489daf0","repo":"dbt-labs/dbt-core","slug":"modelpropertiesentry-guaranteed-to-exist-for-model","errorCode":null,"errorMessage":"ModelPropertiesEntry guaranteed to exist for model","messagePattern":"ModelPropertiesEntry guaranteed to exist for model","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbt-parser/src/resolve/resolve_metrics.rs","lineNumber":163,"sourceCode":"            init_project_config(\n                &package.dbt_project.metrics,\n                (),\n                dependency_package_name,\n                disallow_plus_prefix,\n                adapter_type,\n            )\n        },\n        adapter_type,\n    )?;\n\n    for (model_name, model_props) in typed_models_properties.iter() {\n        if model_props.metrics.is_none() {\n            continue;\n        }\n\n        let mpe = minimal_model_properties\n            .get(model_name)\n            .expect(\"ModelPropertiesEntry guaranteed to exist for model\");\n\n        // For versioned models, `typed_models_properties` contains one entry per\n        // version plus a canonical entry keyed by `mpe.name` pointing at the\n        // latest version. Process only the canonical entry to avoid emitting\n        // duplicate-metric-name errors for a single YAML declaration.\n        if mpe.version_info.is_some() && model_name != &mpe.name {\n            continue;\n        }\n\n        let mut semantic_model_name = model_props.name.clone();\n        if let Some(semantic_model) = &model_props.semantic_model\n            && let Some(name) = &semantic_model.name\n        {\n            semantic_model_name = name.clone();\n        }\n        let semantic_model_unique_id =\n            get_unique_id(&semantic_model_name, package_name, None, \"semantic_model\");\n","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-parser/src/resolve/resolve_metrics.rs#L145-L181","documentation":"Panic \"ModelPropertiesEntry guaranteed to exist for model\" occurs in resolve_nested_model_metrics when `minimal_model_properties.get(model_name)` returns None for a model whose metrics are non-none. The resolver assumes every model iterated from typed_models_properties has a matching entry in minimal_model_properties; divergence between the two collections breaks the invariant.","triggerScenarios":"resolve_metrics processes a model present in the models/metrics input list but absent from minimal_model_properties — e.g., the model's YAML entry was keyed under a versioned name or its properties were filtered out upstream.","commonSituations":"Versioned models where the map is keyed by versioned name vs base name; duplicated YAML files for the same model where one populates typed_models_properties but not minimal_model_properties.","solutions":["Use `.ok_or_else(...)` or skip when the entry is missing instead of expect, logging a warning naming the model.","Ensure both maps are built from the same source list so keying stays consistent (same name normalization).","Check the versioned-model handling above: only process the canonical entry keyed by mpe.name."],"exampleFix":"// before\nlet mpe = minimal_model_properties.get(model_name).expect(\"ModelPropertiesEntry guaranteed to exist for model\");\n// after\nlet mpe = match minimal_model_properties.get(model_name) {\n    Some(mpe) => mpe,\n    None => continue,\n};","handlingStrategy":"fallback","validationCode":"// before resolving, ensure both collections agree\nfor model in &models_with_metrics {\n    debug_assert!(minimal_model_properties.contains_key(model), \"missing MPE for {}\", model);\n}","typeGuard":"fn mpe_of<'a>(map: &'a HashMap<String, ModelPropertiesEntry>, name: &str) -> Option<&'a ModelPropertiesEntry> { map.get(name) }","tryCatchPattern":"// for library users hitting the panic via resolve_metrics, wrap and surface\nlet res = std::panic::catch_unwind(|| resolve_metrics(...));","preventionTips":["Build minimal_model_properties and typed_models_properties from the same source list","Normalize versioned vs base model names identically in both maps","Prefer skip-with-warning over expect for per-model resolution"],"tags":["rust","metrics","panic","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}