jdx/mise · error
expected exactly one Hex OTP build record for {release_tag},
Error message
expected exactly one Hex OTP build record for {release_tag}, found {} What it means
For Linux precompiled OTP, mise downloads builds.txt from builds.hex.pm for the arch/OS and expects exactly one line whose first whitespace-separated field is the release tag OTP-<version>. Zero matches means Bob has not published that version for your arch/OS (too new, too old, or skipped); multiple matches means duplicate records upstream. Fatal when erlang.compile=false; otherwise it becomes a fallback reason and OTP compiles from source.
Source
Thrown at src/plugins/core/erlang.rs:805
lock_platforms
.get(platform_key)
.is_some_and(|pi| pi.install.as_deref() == Some("source"))
} else {
erlang_compile == Some(true)
}
}
fn parse_hex_build_checksum(builds: &str, release_tag: &str) -> Result<String> {
let matching = builds
.lines()
.filter_map(|line| {
let parts = line.split_whitespace().collect::<Vec<_>>();
(parts.first() == Some(&release_tag)).then_some(parts)
})
.collect::<Vec<_>>();
if matching.len() != 1 {
bail!(
"expected exactly one Hex OTP build record for {release_tag}, found {}",
matching.len()
);
}
let checksum = matching[0]
.get(3)
.ok_or_else(|| eyre::eyre!("Hex OTP build record for {release_tag} has no checksum"))?;
if !regex!(r"^[0-9a-f]{64}$").is_match(checksum) {
bail!("invalid Hex OTP checksum for {release_tag}: {checksum}");
}
Ok(format!("sha256:{checksum}"))
}
#[cfg(any(linux, test))]
fn require_locked_precompiled_checksum(version: &str, checksum: Option<&str>) -> Result<String> {
let checksum = checksum.ok_or_else(|| {View on GitHub (pinned to 6f52dcdf99)
Solutions
- Pick a version that exists for your platform: check https://builds.hex.pm/builds/otp/amd64/ubuntu-24.04/builds.txt (substitute your arch/OS) and pin that
- If the version just released, wait a day or two for Bob builds, or temporarily `mise settings set erlang.compile true`
- Verify the version string with `mise ls-remote erlang` — typos produce the same 'found 0' result
- If the file genuinely shows duplicates, report to the hex-core Bob project and use compile=true meanwhile
Example fix
# before $ mise use -p erlang@27.3 # not yet in builds.txt → found 0 # after — pick a published build (or compile) $ mise use -p erlang@27.2 # or: mise settings set erlang.compile true && mise install erlang@27.3
Defensive patterns
Strategy: validation
Validate before calling
# confirm Bob published this OTP for your arch/OS before a compile=false install
VER=27.1; ARCH=amd64; OS=ubuntu-24.04
curl -fsSL "https://builds.hex.pm/builds/otp/$ARCH/$OS/builds.txt" | grep -q "^OTP-$VER " \
&& mise install erlang@$VER \
|| { echo "no Bob build for OTP-$VER on $ARCH/$OS — choosing compile or another version"; exit 1; } Try / catch
if ! mise install erlang@27.1; then # precompiled record missing — either wait for Bob, or build from source mise settings set erlang.compile true && mise install erlang@27.1 fi
Prevention
- Pin OTP patch versions that already appear in builds.txt instead of tracking the newest release
- arm64 builds usually lag amd64 — allow extra settle time before pinning fresh versions on arm64
When it happens
Trigger: `mise install erlang@<v>` with compile=false where <v> is a freshly released OTP patch not yet built by Bob for your os_ver (arm64 typically lags amd64), an old version whose builds were dropped, or a version typo; also `mise lock` with compile=false on the same conditions.
Common situations: Pinning a brand-new OTP within hours of release on an arm64/Ubuntu-24.04 runner; version strings copied from erlang.org announcements before Bob catches up; duplicated upstream records after hex.pm incidents.
Related errors
- invalid Hex OTP checksum for {release_tag}: {checksum}
- precompiled erlang is not available: {reason}
- precompiled erlang is not supported on musl linux
- unsupported architecture: {other}
- unsupported OS version: {os_ver}
AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22).
Data as JSON: /api/errors/eeb253758ed3b611.
Report an issue: GitHub.