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

  1. Clamp or validate month input to 1..=12 before constructing YearMonth
  2. Fix off-by-one month arithmetic with proper wraparound (use year increments when month exceeds 12)
  3. If parsing user input, surface a clear validation message before calling YearMonth
  4. 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

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


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)