{"record":{"id":"a41a71aaef3fb609","repo":"bytedance/deer-flow","slug":"expected-exactly-32-bytes","errorCode":null,"errorMessage":"expected exactly 32 bytes","messagePattern":"expected exactly 32 bytes","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/app/channels/buzz_nostr.py","lineNumber":80,"sourceCode":"        bits += 5\n        if bits >= 8:\n            bits -= 8\n            out.append((acc >> bits) & 0xFF)\n    if len(out) != 32:\n        raise ValueError(f\"expected 32-byte payload in {value!r}\")\n    return bytes(out)\n\n\ndef _parse_32_bytes(value: str, bech_hrp: str) -> bytes:\n    value = value.strip()\n    if value.lower().startswith(f\"{bech_hrp}1\"):\n        return _bech32_decode(bech_hrp, value.lower())\n    try:\n        raw = bytes.fromhex(value)\n    except ValueError as exc:\n        raise ValueError(f\"expected 64-hex or {bech_hrp}1... value\") from exc\n    if len(raw) != 32:\n        raise ValueError(\"expected exactly 32 bytes\")\n    return raw\n\n\ndef parse_private_key(value: str) -> NostrKeys:\n    secret = _parse_32_bytes(value, \"nsec\")\n    coincurve = _require_coincurve()\n    pubkey = coincurve.PrivateKey(secret).public_key.format(compressed=True)[1:]\n    return NostrKeys(secret=secret, pubkey_hex=pubkey.hex())\n\n\ndef parse_pubkey(value: str) -> str:\n    return _parse_32_bytes(value, \"npub\").hex()\n\n\ndef event_id(pubkey_hex: str, created_at: int, kind: int, tags: list[list[str]], content: str) -> str:\n    payload = json.dumps([0, pubkey_hex, created_at, kind, tags, content], separators=(\",\", \":\"), ensure_ascii=False)\n    return hashlib.sha256(payload.encode()).hexdigest()\n","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/channels/buzz_nostr.py#L62-L98","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Count the hex characters — must be exactly 64 (32 bytes).","Re-copy the full key from the source; a single dropped char is the usual cause.","If your value is a different length, you are holding the wrong secret — re-export the Nostr key."],"exampleFix":"# before (63 chars — truncated)\nprivate_key: \"4c0a5c...e\"   # one char short\n\n# after\nprivate_key: \"4c0a5c...e3\"  # exactly 64 hex chars","handlingStrategy":"validation","validationCode":"def hex_is_32_bytes(value: str) -> bool:\n    v = value.strip()\n    return len(v) == 64 and all(c in '0123456789abcdefABCDEF' for c in v)","typeGuard":null,"tryCatchPattern":"try:\n    parse_private_key(raw)\nexcept ValueError as e:\n    if 'exactly 32 bytes' in str(e):\n        raise ConfigError('key must be 64 hex chars — likely truncated paste') from e\n    raise","preventionTips":["Assert len(hex) == 64 in provisioning scripts before writing config.","Use secret managers that store fixed-size values rather than free-form strings.","Watch for clipboard tools that drop leading zeros."],"tags":["buzz","nostr","validation","config"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}