{"record":{"id":"3653fa5b0e2bdb3d","repo":"bytedance/deer-flow","slug":"not-bech32-value-r","errorCode":null,"errorMessage":"not bech32: {value!r}","messagePattern":"not bech32: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/app/channels/buzz_nostr.py","lineNumber":47,"sourceCode":"class NostrKeys:\n    secret: bytes\n    pubkey_hex: str\n\n\ndef _bech32_polymod(values: list[int]) -> int:\n    gen = [0x3B6A57B2, 0x26508E6D, 0x1EA119FA, 0x3D4233DD, 0x2A1462B3]\n    chk = 1\n    for v in values:\n        b = chk >> 25\n        chk = (chk & 0x1FFFFFF) << 5 ^ v\n        for i in range(5):\n            chk ^= gen[i] if ((b >> i) & 1) else 0\n    return chk\n\n\ndef _bech32_decode(expected_hrp: str, value: str) -> bytes:\n    if \"1\" not in value:\n        raise ValueError(f\"not bech32: {value!r}\")\n    hrp, data_part = value.rsplit(\"1\", 1)\n    if hrp != expected_hrp:\n        raise ValueError(f\"expected {expected_hrp!r} bech32, got {hrp!r}\")\n    try:\n        data = [_BECH32_CHARSET.index(c) for c in data_part]\n    except ValueError as exc:\n        raise ValueError(f\"invalid bech32 character in {value!r}\") from exc\n    hrp_expanded = [ord(c) >> 5 for c in hrp] + [0] + [ord(c) & 31 for c in hrp]\n    if _bech32_polymod(hrp_expanded + data) != 1:\n        raise ValueError(f\"bad bech32 checksum in {value!r}\")\n    acc = bits = 0\n    out = bytearray()\n    for v in data[:-6]:\n        acc = (acc << 5) | v\n        bits += 5\n        if bits >= 8:\n            bits -= 8\n            out.append((acc >> bits) & 0xFF)","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/channels/buzz_nostr.py#L29-L65","documentation":"Part of the minimal bech32 decoder used for Nostr nsec/npub keys: _bech32_decode requires a '1' separator between the human-readable part (hrp) and the data part. If the input contains no '1' at all, it cannot even be split, so this ValueError is raised. nsec/npub keys always look like <hrp>1<data>.","triggerScenarios":"channels.buzz config passes a value to parse_private_key/parse_pubkey that starts with 'nsec'/'npub' (or is detected as bech32) but has no '1' separator — e.g. 'nsec', 'npubXYZ', or a truncated key pasted without its data part.","commonSituations":"Copy-paste of a Nostr key that got truncated; typing a key by hand; pasting a hex key with a stray 'nsec' prefix glued on; whitespace-only partial values after strip().","solutions":["Re-copy the full key from your Nostr wallet/client; nsec1... and npub1... always contain a '1' right after the prefix.","Prefer pasting the raw 64-char hex secret instead — _parse_32_bytes also accepts plain hex.","Check for truncation or invisible characters; the value is used as-is after strip().","Never commit the fixed key — rotate it if it was logged."],"exampleFix":"# before\nchannels:\n  buzz:\n    private_key: \"nsec\"\n\n# after (full key or hex)\nchannels:\n  buzz:\n    private_key: \"nsec1<full-data-part>\"","handlingStrategy":"validation","validationCode":"def looks_bech32(value: str, hrp: str) -> bool:\n    v = value.strip().lower()\n    return v.startswith(hrp) and '1' in v[len(hrp):]","typeGuard":null,"tryCatchPattern":"try:\n    keys = parse_private_key(raw)\nexcept ValueError as e:\n    raise SystemExit(f'bad buzz private_key: {e}') from e","preventionTips":["Validate nsec/npub values at config load time, not at first use.","Prefer hex-form keys in automated setups to avoid bech32 edge cases.","Test key parsing in CI with known-good fixtures."],"tags":["buzz","nostr","bech32","validation"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}