bytedance/deer-flow · error · ValueError

expected exactly 32 bytes

Error message

expected exactly 32 bytes

What it means

The hex fallback path of _parse_32_bytes decoded successfully but produced a byte string whose length is not exactly 32. Nostr secrets and pubkeys are 32 bytes (64 hex chars), so a 63/65/66-char hex value or a short fragment raises this ValueError.

Source

Thrown at backend/app/channels/buzz_nostr.py:80

        bits += 5
        if bits >= 8:
            bits -= 8
            out.append((acc >> bits) & 0xFF)
    if len(out) != 32:
        raise ValueError(f"expected 32-byte payload in {value!r}")
    return bytes(out)


def _parse_32_bytes(value: str, bech_hrp: str) -> bytes:
    value = value.strip()
    if value.lower().startswith(f"{bech_hrp}1"):
        return _bech32_decode(bech_hrp, value.lower())
    try:
        raw = bytes.fromhex(value)
    except ValueError as exc:
        raise ValueError(f"expected 64-hex or {bech_hrp}1... value") from exc
    if len(raw) != 32:
        raise ValueError("expected exactly 32 bytes")
    return raw


def parse_private_key(value: str) -> NostrKeys:
    secret = _parse_32_bytes(value, "nsec")
    coincurve = _require_coincurve()
    pubkey = coincurve.PrivateKey(secret).public_key.format(compressed=True)[1:]
    return NostrKeys(secret=secret, pubkey_hex=pubkey.hex())


def parse_pubkey(value: str) -> str:
    return _parse_32_bytes(value, "npub").hex()


def event_id(pubkey_hex: str, created_at: int, kind: int, tags: list[list[str]], content: str) -> str:
    payload = json.dumps([0, pubkey_hex, created_at, kind, tags, content], separators=(",", ":"), ensure_ascii=False)
    return hashlib.sha256(payload.encode()).hexdigest()

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Count the hex characters — must be exactly 64 (32 bytes).
  2. Re-copy the full key from the source; a single dropped char is the usual cause.
  3. If your value is a different length, you are holding the wrong secret — re-export the Nostr key.

Example fix

# before (63 chars — truncated)
private_key: "4c0a5c...e"   # one char short

# after
private_key: "4c0a5c...e3"  # exactly 64 hex chars
Defensive patterns

Strategy: validation

Validate before calling

def hex_is_32_bytes(value: str) -> bool:
    v = value.strip()
    return len(v) == 64 and all(c in '0123456789abcdefABCDEF' for c in v)

Try / catch

try:
    parse_private_key(raw)
except ValueError as e:
    if 'exactly 32 bytes' in str(e):
        raise ConfigError('key must be 64 hex chars — likely truncated paste') from e
    raise

Prevention

When it happens

Trigger: A hex value with one character dropped or added (odd or wrong-length), a 32-hex-char (16-byte) fragment, or a full 64-byte (128-hex) key pasted where a 32-byte one is expected.

Common situations: Clipboard truncation losing one character; pasting a signature or a sha256 digest pair instead of the key; mixing up compressed/uncompressed key formats from other crypto tooling.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/a41a71aaef3fb609. Report an issue: GitHub.