bytedance/deer-flow · error · ValueError
expected 32-byte payload in {value!r}
Error message
expected 32-byte payload in {value!r} What it means
After a valid checksum, the bech32 data part is converted from 5-bit groups back to bytes; the decoder requires exactly 32 bytes because Nostr keys are 32-byte values. If the decoded length differs (too short/long), this ValueError is raised — a structurally valid bech32 string of the wrong length, which for real nsec/npub keys should never happen.
Source
Thrown at backend/app/channels/buzz_nostr.py:67
if hrp != expected_hrp:
raise ValueError(f"expected {expected_hrp!r} bech32, got {hrp!r}")
try:
data = [_BECH32_CHARSET.index(c) for c in data_part]
except ValueError as exc:
raise ValueError(f"invalid bech32 character in {value!r}") from exc
hrp_expanded = [ord(c) >> 5 for c in hrp] + [0] + [ord(c) & 31 for c in hrp]
if _bech32_polymod(hrp_expanded + data) != 1:
raise ValueError(f"bad bech32 checksum in {value!r}")
acc = bits = 0
out = bytearray()
for v in data[:-6]:
acc = (acc << 5) | v
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")View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Generate the key with a standard Nostr client or `python -c "import secrets; print(secrets.token_hex(32))"` and use the hex form.
- Do not hand-craft or modify bech32 strings.
- If a tool produced this value, report the encoding bug to that tool and re-export the key.
Example fix
# generate a fresh key as hex and use it directly python -c "import secrets; print(secrets.token_hex(32))" # -> put the 64-char hex output into channels.buzz.private_key
Defensive patterns
Strategy: validation
Validate before calling
def is_32byte_bech32(value: str, hrp: str) -> bool:
v = value.strip().lower()
if not (v.startswith(hrp + '1') and '1' in v[len(hrp) + 1:]):
return False
data_len = len(v.rsplit('1', 1)[-1]) - 6 # minus checksum
return data_len * 5 // 8 == 32 Try / catch
try:
keys = parse_private_key(raw)
except ValueError:
# generate a fresh, known-good key rather than debugging a hand-made one
raw = secrets.token_hex(32)
keys = parse_private_key(raw) Prevention
- Never hand-craft bech32 values; always generate with standard tooling.
- Add a smoke test that parses a generated key end-to-end at channel startup.
When it happens
Trigger: A bech32 string with a correct checksum but a payload that decodes to something other than 32 bytes — typically a hand-crafted value, a key from a different scheme that happens to carry the nsec/npub hrp, or a value padded/extended in a checksum-consistent way.
Common situations: Very rare in practice; usually indicates someone generated a test/garbage value, or a tool emitted a non-standard encoding. Real nsec1/npub1 keys from any Nostr client are always 32 bytes.
Related errors
- not bech32: {value!r}
- expected {expected_hrp!r} bech32, got {hrp!r}
- invalid bech32 character in {value!r}
- bad bech32 checksum in {value!r}
- expected 64-hex or {bech_hrp}1... value
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/72caba71453ee6e7.
Report an issue: GitHub.