{"record":{"id":"358f4350eddb537a","repo":"BoundaryML/baml","slug":"cannot-parse-end-date","errorCode":null,"errorMessage":"Cannot parse end date","messagePattern":"Cannot parse end date","errorType":"exception","errorClass":"minijinja::Error","httpStatus":null,"severity":"error","filePath":"engine/boundary-udf/src/lib.rs","lineNumber":88,"sourceCode":"    }\n}\n\n// NOTE: (Jesus) Could use real date type\nfn date_between(date: String, begin: String, end: String) -> Result<bool, minijinja::Error> {\n    fn parse_date(date: &str) -> chrono::ParseResult<chrono::NaiveDate> {\n        chrono::NaiveDate::parse_from_str(date, \"%Y-%m-%d\")\n    }\n\n    // NOTE: (Jesus) This will be parsing `begin` and `end` dates for all rows and `date` for all date\n    // comparisons.\n    let Ok(date) = parse_date(&date) else {\n        return Ok(false);\n    };\n    let begin = parse_date(&begin).map_err(|_| {\n        minijinja::Error::new(minijinja::ErrorKind::SyntaxError, \"Cannot parse begin date\")\n    })?;\n    let end = parse_date(&end).map_err(|_| {\n        minijinja::Error::new(minijinja::ErrorKind::SyntaxError, \"Cannot parse end date\")\n    })?;\n\n    Ok(date >= begin && date <= end)\n}\n\npub mod tests {\n    //! Utilities for testing\n    use crate::{config::UDFConfig, read_udf_config};\n\n    pub fn load_sample_udf() -> UDFConfig {\n        use anyhow::Context;\n        read_udf_config(\"./sample-prices.yaml\")\n            .context(\"load sample UDF config\")\n            .unwrap()\n    }\n\n    // NOTE: sample data in here has been generated with the help of AI.\n    pub mod data {","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/boundary-udf/src/lib.rs#L70-L106","documentation":"The date_between Jinja filter parses the row `date`, then the `begin` bound, then the `end` bound. If `end` cannot be parsed into a date by parse_date, the filter raises a minijinja SyntaxError 'Cannot parse end date'. Like the begin bound, an unparseable end is treated as a template error rather than silently false.","triggerScenarios":"Calling date_between(date, begin, end) where `end` is not in the format parse_date accepts (wrong format, empty string, or a non-date expression).","commonSituations":"Templates with a mistyped or locale-formatted end date; computed end values (e.g. concatenated strings) that don't produce a valid date string.","solutions":["Correct the `end` argument to match the format expected by parse_date (e.g. YYYY-MM-DD)","Pre-validate or normalize the end date in the template before calling date_between","Check computed end expressions render to a parseable date string","Ensure the end date is actually later-formatted correctly relative to begin (a swapped begin/end still needs valid formats)"],"exampleFix":"// before\n{{ date_between(post.created_at, \"2024-01-01\", end_date_var) }}\n// after (end_date_var = \"31-12-2024\" -> fix source)\n{% set end_date_var = \"2024-12-31\" %}\n{{ date_between(post.created_at, \"2024-01-01\", end_date_var) }}","handlingStrategy":"validation","validationCode":"const ISO_DATE = /^\\d{4}-\\d{2}-\\d{2}$/;\nif (!ISO_DATE.test(end)) throw new Error(`end must be YYYY-MM-DD, got: ${end}`);","typeGuard":null,"tryCatchPattern":"{% if end is string and end|length == 10 %}\n  {{ date_between(d, begin, end) }}\n{% else %}\n  {{ false }}\n{% endif %}","preventionTips":["Validate computed end-date expressions render parseable strings","Keep begin and end in the same, parse_date-compatible format","Add template smoke tests covering date_between"],"tags":["jinja","date","template"],"backgroundTag":"invalid-date-format","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"}