gleam-lang/gleam · error · ErrorType

ErrorType::ConstantSizeNotPositive

Error message

ErrorType::ConstantSizeNotPositive

What it means

In bit array patterns, a constant size expression evaluating to zero or a negative number makes the segment impossible to match, so the compiler rejects it with `ConstantSizeNotPositive` (checked via `as_int_literal` against `BigInt::ZERO`). This runs only in `TypeOptionsMode::Pattern`; in expressions a negative size is allowed and merely yields an empty segment.

Solutions

  1. Use a positive constant size in the pattern, e.g. `<<_:size(8)>>`.
  2. To match an empty bit array, write the empty pattern `<<>>` instead of `size(0)`.
  3. If the size is variable, use a variable-sized rest segment such as `<<x:bytes>>` or a non-constant size expression.

Example fix

// before
let assert <<x:size(-8)>> = data
// after
let assert <<x:size(8)>> = data
Defensive patterns

Strategy: validation

Validate before calling

// Pattern sizes must be strictly positive constants.
fn valid_pattern_size(n: Int) -> Bool {
  n > 0
}

Prevention

When it happens

Trigger: Pattern matching with `<<_:size(0)>>`, `<<x:size(-8)>>`, or any constant non-positive size literal inside a bit array pattern.

Common situations: Copy-pasting an expression's size spec into a pattern; sizes computed from negative constants; assuming zero-width patterns are legal as they sometimes are in expressions.

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 gleam-lang/gleam@15b07c7830 (2026-09-14). Data as JSON: /api/errors/dae9f07feafff6eb. Report an issue: GitHub.

Appendix: source

Thrown at compiler-core/src/bit_array.rs:334

        ..
    } = categories
        && let Some(abox) = size.value()
    {
        match abox.as_int_literal() {
            None => (),
            Some(value) if value == 16.into() || value == 32.into() || value == 64.into() => (),
            _ => return err(ErrorType::FloatWithSize, size.location()),
        }
    }

    // Segment patterns with a zero or negative constant size must be rejected,
    // we know they will never match!
    // A negative size is still allowed in expressions as it will just result
    // in an empty segment.
    if let (Some(size @ Size { value, .. }), TypeOptionsMode::Pattern) = (categories.size, mode) {
        match value.as_int_literal() {
            Some(n) if n <= BigInt::ZERO => {
                return err(ErrorType::ConstantSizeNotPositive, size.location());
            }
            Some(_) | None => (),
        }
    }

    Ok(categories.segment_type())
}

pub trait GetLiteralValue {
    fn as_int_literal(&self) -> Option<BigInt>;
}

impl GetLiteralValue for ast::TypedPattern {
    fn as_int_literal(&self) -> Option<BigInt> {
        match self {
            ast::Pattern::Int { int_value, .. }
            | ast::Pattern::BitArraySize(ast::BitArraySize::Int { int_value, .. }) => {
                Some(int_value.clone())

View on GitHub (pinned to 15b07c7830)