ArchiveBox/ArchiveBox · error · ValueError

Size value must resolve to a whole number of bytes.

Error message

Size value must resolve to a whole number of bytes.

What it means

parse_filesize_to_bytes accepts floats only if they represent a whole number of bytes; a fractional value like 1024.5 cannot be represented as an exact byte count, so it raises ValueError rather than silently truncating. This keeps size limits exact.

Source

Thrown at archivebox/misc/util.py:296

            yield url


def parse_filesize_to_bytes(value: str | int | float | None) -> int:
    """
    Parse a byte count from an integer or human-readable string like 45mb or 2 GB.
    """
    if value is None:
        return 0

    if isinstance(value, bool):
        raise ValueError("Size value must be an integer or size string.")

    if isinstance(value, int):
        return value

    if isinstance(value, float):
        if not value.is_integer():
            raise ValueError("Size value must resolve to a whole number of bytes.")
        return int(value)

    raw_value = str(value).strip()
    if not raw_value:
        return 0

    if raw_value.isdigit():
        return int(raw_value)

    match = re.fullmatch(r"(?i)(\d+(?:\.\d+)?)\s*([a-z]+)", raw_value)
    if not match:
        raise ValueError(f"Invalid size value: {value}")

    amount_str, unit_str = match.groups()
    multiplier = FILESIZE_UNITS.get(unit_str.lower())
    if multiplier is None:
        raise ValueError(f"Unknown size unit: {unit_str}")

View on GitHub (pinned to 74564b2822)

Solutions

  1. Round to an integer before passing: int(value) or round(value).
  2. Use a size string with a supported unit instead of raw float bytes (e.g. '1.5gb' is handled by the string branch).
  3. Fix the upstream computation to keep byte counts integral.
  4. Sanitize config values with math.floor/ceil at load time.

Example fix

// before
half = total_bytes / 2
parse_filesize_to_bytes(half)
// after
half = total_bytes // 2
parse_filesize_to_bytes(half)
Defensive patterns

Strategy: type-guard

Validate before calling

def whole_bytes_ok(v) -> bool:
    if isinstance(v, float):
        return v.is_integer()
    return isinstance(v, (int, str)) and not isinstance(v, bool)

Type guard

def is_integral(v: object) -> bool:
    return (isinstance(v, int) and not isinstance(v, bool)) or (isinstance(v, float) and v.is_integer())

Try / catch

try:
    n = parse_filesize_to_bytes(value)
except ValueError:
    n = int(float(value))  # only if truncation is acceptable

Prevention

When it happens

Trigger: Calling parse_filesize_to_bytes(1024.5) or a value computed by division (e.g. total/2.0) via clean_snapshot_max_size/clean_crawl_max_size or the add command.

Common situations: Computing sizes with division in a script then feeding the float to ArchiveBox config; JSON/YAML configs containing decimal sizes like 1.5mb entered as raw float 1572864.5; unit conversions done with float math.

Related errors


AI-assisted analysis of ArchiveBox/ArchiveBox@74564b2822 (2026-08-28). Data as JSON: /api/errors/6a75c32cd2b9d3f5. Report an issue: GitHub.