jdx/mise · error

TEMP is too long to replace mise.exe safely ({len} UTF-16 co

Error message

TEMP is too long to replace mise.exe safely ({len} UTF-16 code units)

  TEMP = {tmp}

Updating moves the running mise.exe aside and then launches a helper from TEMP to
put the new one in place. That helper's path would be {helper} UTF-16 code units,
and Windows cannot launch an executable whose path reaches {max}. The move happens
first, so going ahead would leave no mise installed at all.

Point TEMP and TMP at a shorter directory and run mise self-update again:

  $env:TEMP = 'C:\Temp'; $env:TMP = 'C:\Temp'

What it means

Windows self-update moves the running mise.exe aside and then launches a helper from %TEMP% to put the new binary in place. mise pre-computes the helper's path length (UTF-16 code units, stem-aware) and refuses if it would reach MAX_PATH (260) — Windows cannot launch an executable with that path, and because the move happens first, proceeding would leave NO mise installed. The message tells you to point TEMP/TMP at a short directory.

Source

Thrown at src/cli/self_update.rs:270

        let msg = formatdoc! {r#"
            TEMP is too long to replace mise.exe safely ({len} UTF-16 code units)

              TEMP = {tmp}

            Updating moves the running mise.exe aside and then launches a helper from TEMP to
            put the new one in place. That helper's path would be {helper} UTF-16 code units,
            and Windows cannot launch an executable whose path reaches {max}. The move happens
            first, so going ahead would leave no mise installed at all.

            Point TEMP and TMP at a shorter directory and run mise self-update again:

              $env:TEMP = 'C:\Temp'; $env:TMP = 'C:\Temp'"#,
            len = tmp.as_os_str().encode_wide().count(),
            tmp = tmp.display(),
            helper = helper_path_len(&tmp, stem.as_deref()),
            max = MAX_PATH,
        };
        bail!("{msg}");
    }

    fn do_update(&self) -> Result<Status> {
        // Use block_in_place to allow self_update's blocking HTTP calls
        // to work within mise's async runtime
        tokio::task::block_in_place(|| self.do_update_blocking())
    }

    fn do_update_blocking(&self) -> Result<Status> {
        let mut update = Update::configure();
        if let Some((token, _)) = crate::github::resolve_token("github.com") {
            update.auth_token(&token);
        }
        #[cfg(windows)]
        let bin_path_in_archive = "mise/bin/mise.exe";
        #[cfg(not(windows))]
        let bin_path_in_archive = "mise/bin/mise";
        update

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Run in PowerShell: `$env:TEMP = 'C:\Temp'; $env:TMP = 'C:\Temp'` then `mise self-update`
  2. Make the short directory first: `mkdir C:\Temp` if it does not exist
  3. Longer term: enable long-path support or use a shorter Windows username/profile

Example fix

# before
mise self-update   # TEMP deep under the user profile
# after (PowerShell)
mkdir C:\Temp -Force
$env:TEMP = 'C:\Temp'; $env:TMP = 'C:\Temp'
mise self-update
Defensive patterns

Strategy: validation

Validate before calling

# PowerShell: verify TEMP is short enough before self-update
$helperLen = ($env:TEMP + '\mise-self-update-helper-<stem>.exe').Length
if ($helperLen -ge 260) { $env:TEMP = 'C:\Temp'; $env:TMP = 'C:\Temp' }
mise self-update

Prevention

When it happens

Trigger: `mise self-update` on Windows where %TEMP% is deep (long username, nested CI workspaces, MSYS-style temp roots) pushing helper path length to >= 260 UTF-16 units. ensure_temp_dir_can_replace_binary() runs before any file is moved.

Common situations: Machines with long corporate usernames (C:\Users\<40+chars>\AppData\Local\Temp); CI runners with deep workspace temp paths; aggressive TEMP overrides into nested project dirs.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/dcef02ccac687971. Report an issue: GitHub.