{"record":{"id":"b4adc5aa5745a7ab","repo":"pydantic/monty","slug":"index-bounded-by-alphabet-length","errorCode":null,"errorMessage":"index bounded by alphabet length","messagePattern":"index bounded by alphabet length","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/monty/src/modules/base64.rs","lineNumber":925,"sourceCode":"                })?,\n                None => 84,\n            };\n            acc = acc * 85 + u64::from(value);\n        }\n        let word = u32::try_from(acc)\n            .map_err(|_| codec_value_error(format!(\"{codec} overflow in hunk starting at byte {start}\")))?;\n        out.extend_from_slice(&word.to_be_bytes());\n    }\n\n    out.truncate(out.len() - padding);\n    Ok(out)\n}\n\n/// Reverse lookup for a base85 alphabet: index by byte, `None` outside it.\nfn base85_table(alphabet: &[u8; 85]) -> [Option<u8>; 256] {\n    let mut table = [None; 256];\n    for (value, byte) in alphabet.iter().enumerate() {\n        table[usize::from(*byte)] = Some(u8::try_from(value).expect(\"index bounded by alphabet length\"));\n    }\n    table\n}\n\n/// Encodes bytes as Ascii85, five digits per four-byte word.\n///\n/// An all-zero word folds to `z` and, with `foldspaces`, four spaces fold to\n/// `y`. A short final group is zero-padded to a full word and the digits that\n/// padding produced are dropped again unless `pad` is set.\nfn a85_encode(data: &[u8], pad: bool, foldspaces: bool) -> Vec<u8> {\n    let padding = (4 - data.len() % 4) % 4;\n    let mut out: Vec<u8> = Vec::with_capacity(data.len().div_ceil(4) * 5);\n    // Where the final word's digits start, so the padding trim below can\n    // rewrite them the way CPython rewrites `chunks[-1]`.\n    let mut last_start = 0;\n\n    for chunk in data.chunks(4) {\n        last_start = out.len();","sourceCodeStart":907,"sourceCodeEnd":943,"githubUrl":"https://github.com/pydantic/monty/blob/adc986b362e3961f407868cb118a99fe831b9e61/crates/monty/src/modules/base64.rs#L907-L943","documentation":"This is an internal Rust `expect` inside `base85_table`, which builds a 256-entry reverse-lookup table for an Ascii85/base85 alphabet. The `expect` fires only if a value produced by enumerating the 85-element alphabet does not fit in a `u8`, which is impossible since 85 < 256. It is an unreachable-safety net, not an error users can provoke through the base64 module API.","triggerScenarios":"Only reachable if a developer edits `base85_table` or an alphabet constant so the alphabet exceeds 256 entries or the enumerate index exceeds 255 — i.e. a source-level change, not any runtime input.","commonSituations":"Contributors modifying the base85 alphabets (ascii85, RFC 1924, z85) or refactoring the table construction; end users never hit it.","solutions":["Do nothing at runtime; this line cannot fire with the shipped 85-byte alphabets.","If it fires after your edit, restore the alphabet to exactly 85 unique bytes or change the `Some(u8::try_from(value)...)` conversion to match the new table width."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep base85 alphabets at exactly 85 unique bytes; add a debug assertion or unit test on alphabet length/uniqueness if editing the module."],"tags":["rust","internal-invariant","base85"],"backgroundTag":"internal-invariant-violation","analyzedSha":"adc986b362e3961f407868cb118a99fe831b9e61","analyzedAt":"2026-09-13T19:19:18.698Z","contentChangedAt":"2026-09-13T19:19:18.698Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}