jdx/mise · error

erlang does not yet support refs

Error message

erlang does not yet support refs

What it means

mise's built-in Erlang/OTP backend builds from source with kerl when no precompiled build applies (Linux source builds, `erlang.compile` settings, or missing erlef/otp_builds assets). In `install_via_kerl` (src/plugins/core/erlang.rs:563-566) the code matches on the tool request: anything of the form `ref:<git-ref>` hits `unimplemented!("erlang does not yet support refs")` because kerl's `build-install` workflow only understands release versions like `OTP-27.3` or `27.3`. Notably, this panic fires late — after the source tarball is downloaded, checksum-verified, copied into kerl's archives, and after `file::remove_all(tv.install_path())` has already wiped any previous install at that path.

Source

Thrown at src/plugins/core/erlang.rs:565

            .unwrap_or("Erlang/OTP source");
        ctx.pr.set_message(format!("Downloading {display_name}"));
        if !source_path.exists() {
            HTTP.download_file(source_url, &source_path, Some(ctx.pr.as_ref()))
                .await?;
        }
        self.verify_checksum(ctx, &mut tv, &source_path)?;

        let kerl_base_dir = self.kerl_base_dir();
        let kerl_source_path = kerl_base_dir
            .join("archives")
            .join(format!("{}.tar.gz", Self::release_tag(&tv.version)));
        file::create_dir_all(kerl_source_path.parent().unwrap())?;
        file::copy(&source_path, &kerl_source_path)?;

        file::remove_all(tv.install_path())?;
        match &tv.request {
            ToolRequest::Ref { .. } => {
                unimplemented!("erlang does not yet support refs");
            }
            _ => {
                let mut cmd = cmd!(
                    self.kerl_path(),
                    "build-install",
                    &tv.version,
                    &tv.version,
                    tv.install_path()
                )
                .env("MAKEFLAGS", format!("-j{}", num_cpus::get()));
                for (key, value) in source_build_kerl_env(tv.install_env(), &kerl_base_dir) {
                    cmd = match value {
                        Some(value) => cmd.env(key, value),
                        None => cmd.env_remove(key),
                    };
                }
                cmd.run()?;
            }

View on GitHub (pinned to 6bd4a54fad)

Solutions

  1. Use a released version instead: `mise use erlang@28` (or an exact tag like `mise use erlang@27.3.4`) — kerl path fully supports release versions
  2. If you need a specific git state, find the OTP release tag that contains it and install that tag instead of the raw ref
  3. For a truly custom build: compile Erlang manually (kerl or ./configure && make), then point mise at it via `mise use erlang@path:/opt/erlang-custom` rather than a ref request
  4. If this already fired and wiped your install, re-run the install with a released version to restore the tool directory

Example fix

# before (panics: erlang does not yet support refs)
mise use erlang@ref:master
# after
mise use erlang@28
# or point at a manual build:
mise use erlang@path:/opt/erlang-otp-master
Defensive patterns

Strategy: validation

Validate before calling

# reject ref: requests for erlang before mise wipes the install dir
check_erlang_version() {
  case "$1" in
    erlang@ref:*|ref:*) echo "erlang does not support ref: installs (mise)" >&2; return 1 ;;
    erlang@path:*|erlang@[0-9]*|erlang@OTP-*|erlang@latest) return 0 ;;
    erlang@*) return 0 ;;
    *) return 0 ;;
  esac
}
check_erlang_version 'erlang@ref:master' || exit 1

Type guard

# rust: only release-like or path requests are safe for erlang
fn is_safe_erlang_request(req: &str) -> bool {
    let v = req.strip_prefix("erlang@").unwrap_or(req);
    !(v.starts_with("ref:") || v.starts_with("branch:") || v.starts_with("tag:") || v.starts_with("rev:"))
}

Try / catch

# rust: catch the panic signal as an error path is not possible — unimplemented! aborts the task;
# instead pre-check the ToolRequest before install and surface a real error:
if matches!(tv.request, ToolRequest::Ref { .. }) {
    return Err(eyre::eyre!("erlang does not support ref: requests; use a release version or path:"));
}

Prevention

When it happens

Trigger: Installing erlang via a ref request: `mise install erlang@ref:main`, `mise use erlang@ref:master`, `erlang = "ref:somebranch"` in mise.toml, or `mise exec erlang@ref:... -- ...`, in any situation that routes to the kerl source-build path (Linux, or precompiled assets unavailable for the platform/version, or erlang compile settings forcing source). Precompiled releases exist only for release tags, so refs almost always land here.

Common situations: Wanting a bleeding-edge OTP fix from a branch; copying a `ref:` convention used for other mise tools (git/backend tools support refs) and assuming erlang does; CI matrices pinning `erlang@ref:OTP-...` tags; a previous erlang install being silently removed by the `remove_all` right before the panic, leaving the tool version directory gone.

Related errors


AI-assisted analysis of jdx/mise@6bd4a54fad (2026-08-16). Data as JSON: /api/errors/6f24b80f8bc6628e. Report an issue: GitHub.