canopy-network/canopy · error · ValueError

Item too long: {len(item)} bytes (max 255)

Error message

Item too long: {len(item)} bytes (max 255)

What it means

join_len_prefix builds blockchain state keys by joining byte arrays with a single-byte length prefix before each item. Because the prefix is one byte, each item can be at most 255 bytes; the helper raises ValueError when a component exceeds that, since it could not be encoded without corrupting the key framing.

Source

Thrown at plugin/python/contract/contract.py:90

}


# State key prefixes (matching Go)
ACCOUNT_PREFIX = b"\x01"
POOL_PREFIX = b"\x02"
PARAMS_PREFIX = b"\x07"


# Key generation functions (from keys.py)

def join_len_prefix(*items: Optional[bytes]) -> bytes:
    """Join byte arrays with length prefixes."""
    result = bytearray()
    for item in items:
        if not item:
            continue
        if len(item) > 255:
            raise ValueError(f"Item too long: {len(item)} bytes (max 255)")
        result.append(len(item))
        result.extend(item)
    return bytes(result)


def format_uint64(value: Union[int, str]) -> bytes:
    """Format uint64 as big-endian bytes."""
    if isinstance(value, str):
        value = int(value)
    if not isinstance(value, int) or value < 0 or value >= (1 << 64):
        raise ValueError(f"Invalid uint64 value: {value}")
    return struct.pack('>Q', value)


def key_for_account(address: bytes) -> bytes:
    """Generate state database key for an account."""
    return join_len_prefix(ACCOUNT_PREFIX, address)

View on GitHub (pinned to ee8197d91d)

Solutions

  1. Inspect the oversized item at the call site (print len(item)) and determine which component is unexpectedly long; fix the upstream producer to pass raw, bounded bytes (e.g. a 20/32-byte address).
  2. If the item is a serialized protobuf, pass the inner field (e.g. msg.address bytes) rather than the full serialized message.
  3. Validate length at your own boundary before calling: assert len(component) <= 255, and reject or hash over-long user-supplied components.
  4. If a legitimately larger key space is needed, hash the component (e.g. sha256) to a fixed 32 bytes before joining, or change the prefix scheme deliberately.

Example fix

// before
key = key_for_account(serialized_account_msg)  # >255 bytes -> ValueError
// after
key = key_for_account(msg.from_address)  # raw address bytes, <=255
Defensive patterns

Strategy: validation

Validate before calling

def assert_short(b: bytes, name: str) -> bytes:
    if not isinstance(b, (bytes, bytearray)) or len(b) > 255:
        raise ValueError(f"{name} must be <=255 bytes, got {len(b) if b else type(b)}")
    return bytes(b)

key = key_for_account(assert_short(addr, 'address'))

Type guard

def is_key_component(b) -> bool:
    return isinstance(b, (bytes, bytearray)) and 0 < len(b) <= 255

Try / catch

try:
    key = key_for_account(addr)
except ValueError as e:
    if 'Item too long' in str(e):
        logger.error('oversized key component: %s', e)
        return reject_tx()
    raise

Prevention

When it happens

Trigger: Calling key_for_account(address), key_for_fee_params(), or key_for_fee_pool() with a component longer than 255 bytes — e.g. a malformed 256+ byte address, or an accidentally serialized protobuf blob passed where a raw short key component is expected.

Common situations: Passing a serialized protobuf message instead of raw address bytes to key_for_account; a corrupted or truncated state read yielding oversized byte strings; custom plugin code that invents new key components from unbounded user input (long memos, URLs).

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 canopy-network/canopy@ee8197d91d (2026-09-06). Data as JSON: /api/errors/b4e77e3c5795aa4d. Report an issue: GitHub.