jdx/mise · error
cannot relocate : replacement for does not fit ( > bytes)
Error message
cannot relocate {}: replacement for {} does not fit ({} > {} bytes) What it means
Binary relocation rewrites embedded absolute paths (e.g. the brew prefix) in place inside binaries. In-place replacement can only grow a string into the NUL padding that follows it in its slot; when the replacement (new value + remaining suffix + terminator) exceeds the available slot bytes, replace_in_binary bails, because overwriting past the slot would corrupt adjacent data in the binary.
Solutions
- Use a prefix no longer than the bottle's original install path (default /opt/homebrew on macOS, /home/linuxbrew/.linuxbrew on Linux)
- Set MISE_SYSTEM_BREW_PREFIX to the standard short location and place brew there, then re-apply the package
- Reinstall/re-pour the affected formula so the bottle is re-extracted and relocated fresh (a partially relocated keg must be removed first)
Example fix
# before export MISE_SYSTEM_BREW_PREFIX=/very/long/nested/path/to/my/super/long/brew/prefix # after export MISE_SYSTEM_BREW_PREFIX=/home/linuxbrew/.linuxbrew
Defensive patterns
Strategy: validation
Validate before calling
defaultPrefix=$(grep -ao '/[a-z/]*\.linuxbrew\|[a-z/]*brew' one-binary-from-bottle | head -1)
if [ ${#MISE_SYSTEM_BREW_PREFIX} -gt ${#defaultPrefix} ]; then
echo "custom prefix longer than bottle's build prefix — relocation may not fit"
fi Prevention
- Keep the brew prefix at (or shorter than) the bottle's default install path
- Avoid very long custom MISE_SYSTEM_BREW_PREFIX values when pouring bottles
- Remove and re-pour a keg if a previous relocation attempt partially modified its binaries
When it happens
Trigger: replace_in_binary (called by relocate_keg_with_replacements during pour) finds a placeholder occurrence whose replacement value is longer than the C-string slot (string + trailing NUL run minus one terminator) — e.g. relocating a bottle built with a short install path (like /opt/brew) into a much longer custom MISE_SYSTEM_BREW_PREFIX.
Common situations: Choosing an unusually long brew prefix (deep directory names, long usernames) when the bottle was built for the short default /home/linuxbrew/.linuxbrew or /opt/homebrew; relocation between prefixes of very different lengths.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- cannot relocate : not enough padding to grow load commands…
- cannot relocate : rpath must grow but the dynamic string…
- app Info.plist must be a regular file
- app target is outside an allowed Applications directory
- artifact target has changed
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/a311b9256c630d41.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/packages/brew/relocate.rs:178
// keep); find the end at the next NUL
let str_end = content[start..]
.iter()
.position(|&b| b == 0)
.map(|p| start + p)
.unwrap_or(content.len());
// available slot: the string plus the run of NULs after it,
// minus one NUL that must remain as terminator
let slot_end = content[str_end..]
.iter()
.position(|&b| b != 0)
.map(|p| str_end + p)
.unwrap_or(content.len());
let old = content[start..str_end].to_vec();
let mut new = r.value.clone();
new.extend_from_slice(&old[r.placeholder.len()..]);
let slot = slot_end.saturating_sub(start);
if new.len() + 1 > slot {
bail!(
"cannot relocate {}: replacement for {} does not fit ({} > {} bytes)",
path.display(),
String::from_utf8_lossy(r.placeholder),
new.len() + 1,
slot,
);
}
content[start..start + new.len()].copy_from_slice(&new);
for b in &mut content[start + new.len()..slot_end] {
*b = 0;
}
changed = true;
search_from = start + new.len();
}
}
Ok(changed)
}
View on GitHub (pinned to 533346cc37)