BoundaryML/baml · error · minijinja::Error
Cannot parse begin date
Error message
Cannot parse begin date
What it means
The date_between Jinja filter parses the row `date`, then the `begin` bound, then the `end` bound. If `begin` cannot be parsed into a date by parse_date, the filter raises a minijinja SyntaxError 'Cannot parse begin date' instead of returning false (the row date itself failing to parse silently yields false).
Solutions
- Correct the `begin` argument to match the format expected by parse_date (e.g. YYYY-MM-DD)
- Pre-validate or normalize the begin date in the template before calling date_between
- Log/print the failing begin value to confirm what is actually passed
- If the value is dynamic, wrap the filter call so a parse error surfaces the raw input
Example fix
// before
{{ date_between(post.created_at, "01/02/2024", "31/02/2024") }}
// after
{{ date_between(post.created_at, "2024-02-01", "2024-02-29") }} Defensive patterns
Strategy: validation
Validate before calling
const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
if (!ISO_DATE.test(begin)) throw new Error(`begin must be YYYY-MM-DD, got: ${begin}`); Try / catch
{% if begin is string and begin|length == 10 %}
{{ date_between(d, begin, end) }}
{% else %}
{{ false }}
{% endif %} Prevention
- Normalize all template date arguments to the format parse_date expects
- Use ISO 8601 (YYYY-MM-DD) consistently for date strings
- Unit-test template filters with realistic date inputs
When it happens
Trigger: Calling date_between(date, begin, end) where `begin` is not in the format parse_date accepts (wrong format, empty string, or a non-date expression).
Common situations: Templates passing user-supplied or locale-formatted begin dates; hardcoded date strings using a format different from what parse_date expects (e.g. YYYY/MM/DD vs YYYY-MM-DD).
Related errors
- Cannot parse end date
- Expected a statically defined string, not expression
- Failed to get template
- Failed to render template
- InvalidOperation
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/e311489122cf93f9.
Report an issue: GitHub.
Appendix: source
Thrown at engine/boundary-udf/src/lib.rs:85
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
// Use the pointer address to hash the expression
std::ptr::hash(self.0, state);
}
}
// NOTE: (Jesus) Could use real date type
fn date_between(date: String, begin: String, end: String) -> Result<bool, minijinja::Error> {
fn parse_date(date: &str) -> chrono::ParseResult<chrono::NaiveDate> {
chrono::NaiveDate::parse_from_str(date, "%Y-%m-%d")
}
// NOTE: (Jesus) This will be parsing `begin` and `end` dates for all rows and `date` for all date
// comparisons.
let Ok(date) = parse_date(&date) else {
return Ok(false);
};
let begin = parse_date(&begin).map_err(|_| {
minijinja::Error::new(minijinja::ErrorKind::SyntaxError, "Cannot parse begin date")
})?;
let end = parse_date(&end).map_err(|_| {
minijinja::Error::new(minijinja::ErrorKind::SyntaxError, "Cannot parse end date")
})?;
Ok(date >= begin && date <= end)
}
pub mod tests {
//! Utilities for testing
use crate::{config::UDFConfig, read_udf_config};
pub fn load_sample_udf() -> UDFConfig {
use anyhow::Context;
read_udf_config("./sample-prices.yaml")
.context("load sample UDF config")
.unwrap()
}View on GitHub (pinned to bd85ce9dee)