jdx/mise · error · eyre::Report
malformed load command table in {}
Error message
malformed load command table in {} What it means
While scanning the ncmds load commands of a 64-bit Mach-O, the running offset reached the end of the table (lc_end = 32 + sizeofcmds) before all commands were read — at least 8 bytes are needed per command header. The declared table size and command count disagree, so the file is treated as malformed.
Source
Thrown at src/system/packages/brew/macho.rs:85
// not a 64-bit LE Mach-O (32-bit or big-endian) — nothing modern on
// arm64 macOS; leave it to the caller's generic byte-level pass
return Ok(false);
}
let ncmds = u32_at(slice, 16) as usize;
let sizeofcmds = u32_at(slice, 20) as usize;
if HEADER_SIZE_64 + sizeofcmds > slice.len() {
bail!("malformed Mach-O in {}", path.display());
}
// upper bound for growing the load-command table: the first byte of
// section data (everything between sizeofcmds and there is padding)
let lc_end = HEADER_SIZE_64 + sizeofcmds;
let mut first_data = slice.len();
{
let mut off = HEADER_SIZE_64;
for _ in 0..ncmds {
if off + 8 > lc_end {
bail!("malformed load command table in {}", path.display());
}
let cmd = u32_at(slice, off);
let cmdsize = u32_at(slice, off + 4) as usize;
if cmdsize < 8 || off + cmdsize > lc_end {
bail!("malformed load command in {}", path.display());
}
if cmd == LC_SEGMENT_64 {
let nsects = u32_at(slice, off + 64) as usize;
for i in 0..nsects {
// struct section_64 is 80 bytes; offset field at +48
let sect = off + 72 + i * 80;
if sect + 80 > off + cmdsize {
break;
}
let file_off = u32_at(slice, sect + 48) as usize;
if file_off > 0 {
first_data = first_data.min(file_off);
}View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Re-download the bottle (clear cache) and retry the pour
- Cross-check with otool -l — inconsistency visible there confirms file corruption
- Report upstream if the file is reproducibly valid elsewhere
Defensive patterns
Strategy: validation
Validate before calling
// Verify ncmds commands fit within sizeofcmds before patching.
fn load_command_table_ok(slice: &[u8]) -> bool {
let ncmds = u32_at(slice, 16) as usize;
let lc_end = 32 + u32_at(slice, 20) as usize;
let mut off = 32;
for _ in 0..ncmds {
if off + 8 > lc_end { return false; }
off += u32_at(slice, off + 4) as usize;
}
true
} Type guard
fn macho_table_walkable(slice: &[u8]) -> bool {
macho_header_ok(slice) && load_command_table_ok(slice)
} Try / catch
if let Err(e) = patch_macho(&mut content, &replacements, &path) {
// log and skip this artifact rather than failing the whole pour
warn!("{}: skipping Mach-O relocation: {e:#}", path.display());
} Prevention
- Validate bottle integrity (sha256) before extraction
- Use otool -l as ground truth when triaging malformed-table reports
When it happens
Trigger: patch_slice first scan loop: off + 8 > lc_end before ncmds iterations complete. Produced by corrupted headers where sizeofcmds is too small for ncmds, or by fuzzed/hand-crafted Mach-O files.
Common situations: Corrupted bottle artifacts; files damaged in transit or by disk issues; test/fuzz binaries with deliberately inconsistent headers.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- malformed Mach-O in {}
- malformed load command in {}
- cannot relocate {}: not enough padding to grow load commands
- malformed fat header in {}
- malformed fat arch in {}
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/55534a24e2636d0f.
Report an issue: GitHub.