Skip to content

fix(activate): handle empty __MISE_FLAGS array with set -u on bash 3.2#8988

Merged
jdx merged 1 commit intomainfrom
fix/bash-activate-nounset
Apr 10, 2026
Merged

fix(activate): handle empty __MISE_FLAGS array with set -u on bash 3.2#8988
jdx merged 1 commit intomainfrom
fix/bash-activate-nounset

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Apr 10, 2026

Summary

  • Use ${arr[@]+"${arr[@]}"} pattern to safely expand the __MISE_FLAGS array when empty
  • Bash < 4.4 (including macOS's default bash 3.2) treats "${arr[@]}" on an empty array as an unbound variable under set -u (nounset)
  • This causes scripts that source .bashrc (which contains eval "$(mise activate bash)") to fail with: __MISE_FLAGS[@]: unbound variable

Test plan

  • Verified the bug reproduces on bash 3.2 (via docker run bash:3.2) with set -u and empty __MISE_FLAGS=()
  • Verified the fix works on bash 3.2 with set -u and empty flags
  • Verified non-empty flags still pass through correctly (--status)
  • Snapshot tests updated and passing

Fixes #8987

🤖 Generated with Claude Code


Note

Low Risk
Low risk: small change to Bash activation script argument expansion, mainly affecting older Bash with set -u; behavior should be unchanged when flags are present.

Overview
Fixes Bash activation hooks to safely expand __MISE_FLAGS even when the array is empty under set -u (notably on Bash 3.2), by switching to the ${arr[@]+"${arr[@]}"} expansion pattern.

Updates the corresponding snapshot (mise__shell__bash__tests__activate.snap) to match the new generated activation script output.

Reviewed by Cursor Bugbot for commit 15c7af0. Bugbot is set up for automated code reviews on this repo. Configure here.

Use ${arr[@]+"${arr[@]}"} pattern to safely expand the __MISE_FLAGS
array when it is empty. Bash < 4.4 (including macOS's default bash 3.2)
treats "${arr[@]}" on an empty array as an unbound variable under
set -u (nounset), causing scripts that source .bashrc to fail with:

  __MISE_FLAGS[@]: unbound variable

Fixes #8987

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@jdx jdx force-pushed the fix/bash-activate-nounset branch from b4c7f99 to 15c7af0 Compare April 10, 2026 02:00
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 10, 2026

Greptile Summary

Fixes a bash 3.2 / set -u compatibility bug where "${__MISE_FLAGS[@]}" on an empty array was treated as an unbound variable under nounset, crashing scripts that source .bashrc after eval "$(mise activate bash)". The fix replaces all three occurrences with the standard ${__MISE_FLAGS[@]+"${__MISE_FLAGS[@]}"} safe-expansion idiom, and the snapshot is updated to match.

Confidence Score: 5/5

Safe to merge — minimal, well-understood shell quoting fix with no regressions.

The ${arr[@]+"${arr[@]}"} idiom is the canonical solution for this exact bash 3.2 nounset/empty-array issue, applied consistently at all three call sites. The non-empty path is covered by the snapshot test (which passes), and the empty-array path was manually verified on bash 3.2 per the PR description. No logic changes outside the expansion syntax.

No files require special attention.

Important Files Changed

Filename Overview
src/assets/bash/activate.sh Replaces "${__MISE_FLAGS[@]}" with the safe ${arr[@]+"${arr[@]}"} idiom in all three hook-env call sites, correctly fixing the bash 3.2 nounset crash.
src/shell/snapshots/mise__shell__bash__tests__activate.snap Snapshot updated to reflect the new safe array expansion syntax; consistent with the source change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Hook function called"] --> B{"__MISE_FLAGS empty?"}
    B -- "Yes" --> C["Safe expansion produces nothing\nNo nounset error on bash 3.2"]
    B -- "No" --> D["Flags expanded correctly\ne.g. --status"]
    C --> E["mise hook-env -s bash"]
    D --> E
    E --> F["eval output"]
Loading

Reviews (2): Last reviewed commit: "fix(activate): handle empty __MISE_FLAGS..." | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the Bash activation script and its snapshots to use a conditional array expansion for __MISE_FLAGS, which avoids 'unbound variable' errors when set -u is active. The review feedback correctly identifies that the new expansion is unquoted, which will cause word splitting issues if any array elements contain spaces.

_mise_hook() {
local previous_exit_status=$?
eval "$(mise hook-env "${__MISE_FLAGS[@]}" -s bash)"
eval "$(mise hook-env ${__MISE_FLAGS[@]+"${__MISE_FLAGS[@]}"} -s bash)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The expansion ${__MISE_FLAGS[@]+"${__MISE_FLAGS[@]}"} is unquoted, which makes it subject to word splitting by the shell (using IFS). If any element in __MISE_FLAGS contains spaces (for example, a path provided via a flag), it will be incorrectly split into multiple arguments before being passed to the mise function. While this pattern is a standard workaround for the set -u issue in Bash versions prior to 4.4, it is only fully safe if the array elements are guaranteed not to contain IFS characters or if IFS is temporarily cleared.

return $previous_exit_status
fi
eval "$(mise hook-env "${__MISE_FLAGS[@]}" -s bash --reason precmd)"
eval "$(mise hook-env ${__MISE_FLAGS[@]+"${__MISE_FLAGS[@]}"} -s bash --reason precmd)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This expansion is unquoted and subject to word splitting, which may cause issues if __MISE_FLAGS contains elements with spaces.

local previous_exit_status=$?
__MISE_BASH_CHPWD_RAN=1
eval "$(mise hook-env "${__MISE_FLAGS[@]}" -s bash --reason chpwd)"
eval "$(mise hook-env ${__MISE_FLAGS[@]+"${__MISE_FLAGS[@]}"} -s bash --reason chpwd)"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This expansion is unquoted and subject to word splitting, which may cause issues if __MISE_FLAGS contains elements with spaces.

@jdx jdx enabled auto-merge (squash) April 10, 2026 02:05
@jdx jdx merged commit e3d374e into main Apr 10, 2026
36 checks passed
@jdx jdx deleted the fix/bash-activate-nounset branch April 10, 2026 02:15
@github-actions
Copy link
Copy Markdown

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.7 x -- echo 21.7 ± 0.4 21.2 25.1 1.00
mise x -- echo 22.2 ± 0.4 21.5 26.0 1.02 ± 0.03

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.7 env 21.4 ± 0.7 20.6 27.2 1.00
mise env 21.7 ± 0.3 21.0 23.1 1.02 ± 0.04

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.7 hook-env 21.9 ± 0.4 21.2 23.6 1.00
mise hook-env 22.3 ± 0.4 21.6 26.3 1.02 ± 0.03

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.4.7 ls 19.3 ± 0.4 18.7 24.0 1.00
mise ls 19.8 ± 0.5 19.1 21.6 1.02 ± 0.03

xtasks/test/perf

Command mise-2026.4.7 mise Variance
install (cached) 146ms 147ms +0%
ls (cached) 76ms 76ms +0%
bin-paths (cached) 80ms 81ms -1%
task-ls (cached) 821ms 803ms +2%

mise-en-dev added a commit that referenced this pull request Apr 10, 2026
### 🚀 Features

- **(config)** add lockfile_platforms setting to restrict lockfile
platforms by @cameronbrill in
[#8966](#8966)
- **(sandbox)** support wildcard patterns in allow_env by @jdx in
[#8974](#8974)
- bump usage-lib v2 → v3 to render examples in task --help by @baby-joel
in [#8890](#8890)

### 🐛 Bug Fixes

- **(activate)** handle empty __MISE_FLAGS array with set -u on bash 3.2
by @jdx in [#8988](#8988)
- **(env)** add trace logging for module hook PATH diagnostics by @jdx
in [#8981](#8981)
- **(go)** Query module proxy directly for version resolution by @c22 in
[#8968](#8968)
- **(install)** render tera templates in tool postinstall hooks by @jdx
in [#8978](#8978)
- **(install)** add missing env vars to tool postinstall hooks by @jdx
in [#8977](#8977)
- **(task)** prevent hang when skipped task has dependents by @jdx in
[#8937](#8937)
- **(task)** invalidate dependent task sources when dependency runs by
@jdx in [#8975](#8975)
- **(task)** prevent deadlock when MISE_JOBS=1 with sub-task references
by @jdx in [#8976](#8976)
- **(task)** fetch remote task files before parsing usage specs by @jdx
in [#8979](#8979)
- **(task)** prevent panic when running parallel sub-tasks with
replacing output by @jdx in
[#8986](#8986)
- **(upgrade)** update lockfile and config when upgrading to specific
version by @jdx in [#8983](#8983)

### 📚 Documentation

- **(node)** remove "recommended for teams" from pin example by @jdx in
[b334363](b334363)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:alpine docker digest to 17a29f2 by
@renovate[bot] in [#8995](#8995)
- update docker/dockerfile:1 docker digest to 2780b5c by @renovate[bot]
in [#8994](#8994)

### New Contributors

- @baby-joel made their first contribution in
[#8890](#8890)
- @cameronbrill made their first contribution in
[#8966](#8966)
- @c22 made their first contribution in
[#8968](#8968)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant