BoundaryML/baml · error

invalid Span range: start ({start}) > end ({end})

Error message

invalid Span range: start ({start}) > end ({end})

What it means

A Span (file location range) failed to deserialize because the encoded start offset is greater than the end offset. Spans are (file_id, start, end) triples serialized with borsh; TextRange::new would panic on end < start, so the deserializer converts the malformed envelope into a clean std::io error with ErrorKind::InvalidData instead of crashing the thread. This means the serialized data was corrupt, truncated, or produced by an incompatible writer.

Source

Thrown at baml_language/crates/baml_base/src/core_types.rs:117

    fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
        BorshSerialize::serialize(&self.file_id, writer)?;
        let start: u32 = self.range.start().into();
        let end: u32 = self.range.end().into();
        BorshSerialize::serialize(&start, writer)?;
        BorshSerialize::serialize(&end, writer)?;
        Ok(())
    }
}

impl BorshDeserialize for Span {
    fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
        let file_id = FileId::deserialize_reader(reader)?;
        let start = u32::deserialize_reader(reader)?;
        let end = u32::deserialize_reader(reader)?;
        // `TextRange::new` panics on `end < start`. A malformed envelope
        // should surface as a clean borsh error rather than a thread crash.
        if start > end {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidData,
                format!("invalid Span range: start ({start}) > end ({end})"),
            ));
        }
        Ok(Span {
            file_id,
            range: TextRange::new(TextSize::new(start), TextSize::new(end)),
        })
    }
}

impl Default for Span {
    /// Creates a sentinel span that doesn't refer to any real file.
    ///
    /// Uses `u32::MAX` as the file ID to avoid conflicts with real files.
    fn default() -> Self {
        Self::fake()
    }

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Delete the stale cache/index artifact that is being deserialized and regenerate it.
  2. Verify the reader is positioned at the correct offset in the stream so fields are not read shifted (file_id, start, end).
  3. Ensure producer and consumer use the same version of the Span serialization format.
  4. Validate the source data ranges (start <= end) before serializing Spans.

Example fix

// before: blindly trust cached spans
let span = Span::deserialize_reader(&mut reader)?;
// after: tolerate corrupt caches by rebuilding
let span = Span::deserialize_reader(&mut reader)
    .map_err(|e| { fs::remove_file(&cache_path).ok(); e })?;
Defensive patterns

Strategy: validation

Validate before calling

// validate before serializing / after deserializing
fn valid_span(start: u32, end: u32) -> bool { start <= end }

Type guard

fn is_valid_span(s: &Span) -> bool { s.start <= s.end }

Try / catch

match Span::deserialize_reader(&mut reader) {
    Ok(span) => span,
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {
        // rebuild/regenerate the corrupted artifact
        regenerate(&path)?
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling Span::deserialize_reader (e.g. while loading a persisted index, cache, or IPC payload) on bytes where the u32 start field exceeds the u32 end field.

Common situations: Stale or hand-edited cache files from an older BAML version with a different serialization layout; byte-order/offset desync when reading a concatenated stream at the wrong position; corrupted incremental-compilation artifacts.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/ea143eff220fcd0d. Report an issue: GitHub.