headroomlabs-ai/headroom · error · ValueError

min_batch_bytes must be positive

Error message

min_batch_bytes must be positive

What it means

Argument-validation ValueError from build/plan-compression-batches in compression_batches.py: min_batch_bytes was <= 0. The batching function groups small compression units into shared batches and requires a positive floor before it will flush a pending batch; zero or negative floors make the greedy grouping meaningless, so it fails fast.

Source

Thrown at headroom/transforms/compression_batches.py:76


def build_compression_batches(
    entries: list[CompressionBatchEntry],
    *,
    min_batch_bytes: int,
    max_batch_bytes: int = DEFAULT_MAX_BATCH_BYTES,
    max_batch_units: int = DEFAULT_MAX_BATCH_UNITS,
) -> tuple[list[CompressionBatch], list[CompressionBatchEntry]]:
    """Greedily group compatible small units and skip under-floor tails.

    Callers retain the skipped entries as normal ``size_floor`` results. The
    function deliberately does not turn a unit larger than the configured
    batch ceiling into a singleton batch; those units belong to the existing
    independent compression path.
    """

    if min_batch_bytes <= 0:
        raise ValueError("min_batch_bytes must be positive")
    if max_batch_bytes < min_batch_bytes:
        raise ValueError("max_batch_bytes must be at least min_batch_bytes")
    if max_batch_units <= 0:
        raise ValueError("max_batch_units must be positive")

    batches: list[CompressionBatch] = []
    skipped: list[CompressionBatchEntry] = []
    pending: list[CompressionBatchEntry] = []
    pending_bytes = 0
    pending_key: tuple[object, ...] | None = None

    def flush() -> None:
        nonlocal pending, pending_bytes, pending_key
        if not pending:
            return
        if pending_bytes >= min_batch_bytes:
            batches.append(CompressionBatch(entries=tuple(pending), text_bytes=pending_bytes))
        else:

View on GitHub (pinned to 322425c43b)

Solutions

  1. Set min_batch_bytes to a positive byte count (e.g. 2048).
  2. If you intended 'no batching', disable batching at the caller level rather than passing 0.
  3. Validate config at load time so the failure surfaces at startup, not mid-compression.

Example fix

# before
plan = group_batches(entries, min_batch_bytes=0)

# after
MIN_BATCH_BYTES = 2048
assert MIN_BATCH_BYTES > 0
plan = group_batches(entries, min_batch_bytes=MIN_BATCH_BYTES)
Defensive patterns

Strategy: validation

Validate before calling

if min_batch_bytes <= 0:
    raise ConfigError("min_batch_bytes must be > 0")
result = group_batches(entries, min_batch_bytes=min_batch_bytes)

Try / catch

try:
    batches, skipped = group_batches(entries, min_batch_bytes=v)
except ValueError as e:
    if "min_batch_bytes" in str(e):
        batches, skipped = group_batches(entries, min_batch_bytes=2048)  # safe default
    else:
        raise

Prevention

When it happens

Trigger: Calling the batch-grouping function with min_batch_bytes=0 or a negative value — typically from a config where the field was left unset (defaulting to 0) or computed as a difference that went negative.

Common situations: A settings file with min_batch_bytes: 0 meaning 'no minimum' to the author; deriving the value from a percentage of a zero-sized budget; copying an example config that omitted the field.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/1d39cf09703b1d28. Report an issue: GitHub.