jdx/mise · error · eyre::Report
malformed load command in {}
Error message
malformed load command in {} What it means
A single load command in a 64-bit Mach-O declared a cmdsize smaller than the mandatory 8-byte command header, or large enough to run past the end of the load-command table. Since the parser steps through commands by cmdsize, an invalid size would desynchronize the whole table, so it bails.
Source
Thrown at src/system/packages/brew/macho.rs:90
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);
}
}
}
off += cmdsize;
}
}View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Clear the bottle cache and re-pour from a fresh download
- Validate with otool -l <file>; malformed size fields will fail there too if the file is truly corrupt
- Report the specific binary upstream if it is reproducibly patchable by ruby-macho/otool
Defensive patterns
Strategy: validation
Validate before calling
// Check each command's size is at least 8 and stays inside the table.
fn command_sizes_ok(slice: &[u8]) -> bool {
let lc_end = 32 + u32_at(slice, 20) as usize;
let mut off = 32;
for _ in 0..u32_at(slice, 16) as usize {
if off + 8 > lc_end { return false; }
let cmdsize = u32_at(slice, off + 4) as usize;
if cmdsize < 8 || off + cmdsize > lc_end { return false; }
off += cmdsize;
}
true
} Type guard
fn macho_commands_wellformed(slice: &[u8]) -> bool {
macho_header_ok(slice) && command_sizes_ok(slice)
} Try / catch
match patch_macho(&mut content, &replacements, &path) {
Ok(_) => {}
Err(e) => warn!("{}: malformed Mach-O, left unpatched: {e:#}", path.display()),
} Prevention
- Checksum bottles before pouring; malformed command sizes almost always mean corruption
- Report binaries that otool parses fine but the rewriter rejects — parser gaps matter upstream
When it happens
Trigger: patch_slice first scan loop: cmdsize < 8 || off + cmdsize > lc_end for some command. Happens with corrupted or malformed binaries where a command's size field is zero/garbage, or where sizeofcmds under-reports the table extent.
Common situations: Truncated or bit-flipped bottle artifacts; Mach-O files processed by broken tooling; fuzzing corpora.
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 table 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/f61b50ccda0572a7.
Report an issue: GitHub.