{"record":{"id":"cf6e675861c7e561","repo":"BoundaryML/baml","slug":"expected-a-null-value","errorCode":null,"errorMessage":"Expected a null value","messagePattern":"Expected a null value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-lib/baml-types/src/value_expr.rs","lineNumber":576,"sourceCode":"\n    pub fn resolve_map(&self, ctx: &impl GetEnvVar) -> Result<IndexMap<String, ResolvedValue>> {\n        match self.resolve(ctx) {\n            Ok(ResolvedValue::Map(m, ..)) => Ok(m.into_iter().map(|(k, (_, v))| (k, v)).collect()),\n            _ => Err(anyhow::anyhow!(\"Expected a map\")),\n        }\n    }\n\n    pub fn resolve_numeric(&self, ctx: &impl GetEnvVar) -> Result<String> {\n        match self.resolve(ctx) {\n            Ok(ResolvedValue::Numeric(n, ..)) => Ok(n),\n            _ => Err(anyhow::anyhow!(\"Expected a numeric value\")),\n        }\n    }\n\n    pub fn resolve_null(&self, ctx: &impl GetEnvVar) -> Result<()> {\n        match self.resolve(ctx) {\n            Ok(ResolvedValue::Null(..)) => Ok(()),\n            _ => Err(anyhow::anyhow!(\"Expected a null value\")),\n        }\n    }\n\n    pub fn resolve_serde<T: serde::de::DeserializeOwned>(&self, ctx: &impl GetEnvVar) -> Result<T> {\n        let value = self.resolve(ctx)?;\n        let value: serde_json::Value = value.try_into()?;\n        match serde_json::from_value(value) {\n            Ok(v) => Ok(v),\n            Err(e) => Err(anyhow::anyhow!(\"Failed to deserialize value: {e}\")),\n        }\n    }\n\n    /// Resolve and deserialize, with support for template_string calls.\n    pub fn resolve_serde_with_templates<T: serde::de::DeserializeOwned>(\n        &self,\n        ctx: &impl GetEnvVar,\n        template_renderer: &impl TemplateStringRenderer,\n    ) -> Result<T> {","sourceCodeStart":558,"sourceCodeEnd":594,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/baml-types/src/value_expr.rs#L558-L594","documentation":"ValueExpr::resolve_null asserts that an expression resolves to ResolvedValue::Null, used when config explicitly expects a null value. Any other resolved variant (or a resolution failure) produces the opaque 'Expected a null value' error, hiding the real cause.","triggerScenarios":"Calling resolve_null on an expression that resolves to any concrete value — a string, number, array, or map — e.g. code that treats an optional field as null when the user actually supplied a value.","commonSituations":"Optional config fields where the developer assumed the default was null but a value was set; env var interpolation that turned 'null' into the string \"null\" rather than a real null.","solutions":["Resolve with resolve() first to check the actual variant instead of asserting null blindly.","If the value should be null, remove or unset the config field / env var so it resolves to Null.","If 'null' comes from a string literal, use JSON null in config rather than the quoted string \"null\".","Match on ResolvedValue yourself and treat Null as one case rather than erroring.","Add an explicit default of null in the config schema if the field is optional."],"exampleFix":"// before (config sets value: \"null\" as a string)\nexpr.resolve_null(&ctx)?; // Err: Expected a null value\n// after\n// config: value null (unquoted JSON null)\nexpr.resolve_null(&ctx)?;","handlingStrategy":"type-guard","validationCode":"let resolved = expr.resolve(&ctx)?;\nif !matches!(resolved, ResolvedValue::Null(_)) {\n    bail!(\"expected null, got: {resolved:?}\");\n}","typeGuard":"fn is_null(v: &ResolvedValue) -> bool { matches!(v, ResolvedValue::Null(..)) }","tryCatchPattern":"if let Err(e) = expr.resolve_null(&ctx) {\n    log::debug!(\"value present, not null: {e}\");\n}","preventionTips":["Use unquoted JSON null in config, not the string \"null\".","Unset optional fields rather than assigning placeholder values.","Match on ResolvedValue instead of asserting a single variant when the value is optional.","Document which fields are nullable in the config schema."],"tags":["rust","baml","type-mismatch","null"],"backgroundTag":"type-mismatch","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}