influxdata/influxdb · warning · YearMonthError
invalid month , expected 1-12
Error message
invalid month {0}, expected 1-12 What it means
YearMonthError::InvalidMonth is returned when constructing or validating a YearMonth with a month value outside 1–12 (e.g. 0 or 13). YearMonth represents a validated year+month pair used for retention/compaction windows. Validation is deliberate so downstream code can assume a valid calendar month.
Solutions
- Clamp or validate month input to 1..=12 before constructing YearMonth
- Fix off-by-one month arithmetic with proper wraparound (use year increments when month exceeds 12)
- If parsing user input, surface a clear validation message before calling YearMonth
- Check config for typos like month=13 or 0-based month values
Example fix
// before let ym = YearMonth::new(2026, 13)?; // InvalidMonth(13) // after assert!((1..=12).contains(&month)); let ym = YearMonth::new(2026, month)?;
Defensive patterns
Strategy: validation
Validate before calling
fn valid_month(m: u8) -> Result<u8, String> {
if (1..=12).contains(&m) { Ok(m) } else { Err(format!("month {} out of range 1-12", m)) }
} Type guard
fn is_valid_month(m: u8) -> bool { (1..=12).contains(&m) } Try / catch
match YearMonth::new(y, m) {
Err(YearMonthError::InvalidMonth(bad)) => {
eprintln!("month {} invalid; using current month", bad);
YearMonth::current()
}
r => r?,
} Prevention
- Clamp month values from config/CLI to 1..=12 at parse time
- Use date libraries (chrono) for month arithmetic to get wraparound for free
- Reject 0-based months from clients early with a clear message
- Unit-test retention config parsing with boundary months (0, 1, 12, 13)
When it happens
Trigger: Calling YearMonth::new(year, month) or a parser with month > 12 or month == 0, e.g. from user-supplied retention period settings or computed month arithmetic that overflows December.
Common situations: Config files specifying retention_window in months with an out-of-range value; arithmetic like month+1 without wraparound; parsing API query parameters where a client sends 13 for a month.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- All `DataPoints` must have at least one field. Builder…
- call site contains null bytes
- Custom partition template must have at least one part
- Custom partition template specified
- database name ' ' contains invalid character, character…
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/1b5acc358d117bf0.
Report an issue: GitHub.
Appendix: source
Thrown at influxdb3_write/src/lib.rs:427
}
}
}
/// A year-month value in YYYY-MM format (e.g., "2025-01").
///
/// Used for organizing snapshot checkpoints by month. Stores year and month
/// as integers for efficient comparison and sorting, while serializing to
/// the standard "YYYY-MM" string format for backward compatibility.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct YearMonth {
year: u16,
month: u8,
}
/// Error type for invalid YearMonth values.
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum YearMonthError {
#[error("invalid month {0}, expected 1-12")]
InvalidMonth(u8),
#[error("invalid year-month format: {0}, expected YYYY-MM")]
InvalidFormat(String),
}
impl YearMonth {
/// Create a YearMonth from year and month without validation.
///
/// # Safety
/// Use only when the values are known to be valid (e.g., from chrono).
/// In debug builds, panics if month is not in 1-12.
pub fn new_unchecked(year: u16, month: u8) -> Self {
debug_assert!((1..=12).contains(&month), "month must be 1-12");
Self { year, month }
}
/// Get the year component.
pub fn year(&self) -> u16 {View on GitHub (pinned to 06200ef96b)