-
Notifications
You must be signed in to change notification settings - Fork 6.4k
Description
Preflight Checklist
- I have searched existing issues and this hasn't been reported yet
- This is a single bug report (please file separate reports for different bugs)
- I am using the latest version of Claude Code
What's Wrong?
Claude Code's shell snapshot mechanism captures function definitions but not variable type declarations (e.g., typeset -gA for associative arrays). This causes runtime errors when captured functions reference arrays that were declared during shell initialization but aren't included in the snapshot.
This is part of a broader pattern of shell snapshot problems:
- Shell snapshots have /usr/bin prepended to PATH, breaking conda #21832 - Shell snapshots prepend
/usr/binto PATH, breaking conda - Shell snapshot breaks zoxide cd wrapper - __zoxide_z not found #20464 - Shell snapshot breaks zoxide
__zoxide_zfunction - Shell snapshot duplicates '--' prefix for aliases, causing parse errors #16545 - Shell snapshot duplicates
--prefix for aliases - [BUG] Shell snapshot overwrites PATH, breaking Homebrew tools (node, npm, gh) #22730 - Shell snapshot overwrites PATH, breaking Homebrew tools
- Shell snapshot subprocesses leaked on every session start (orphaned zsh/bash, zombies) #24564 - Shell snapshot subprocesses leaked (zombies)
What Should Happen?
When mise activates in .zshrc, it generates:
typeset -gA _mise_cnf_tried # Declares associative array
command_not_found_handler() {
_mise_cnf_tried["$cmd"]=1 # Uses it as associative array
}The snapshot should capture both the typeset -gA declaration and the function. Currently it only captures the function, so zsh doesn't know _mise_cnf_tried is an associative array and fails when trying to use string keys.
Error Messages/Logs
command_not_found_handler:17: _mise_cnf_tried: assignment to invalid subscript range
Steps to Reproduce
-
Install mise and activate it in
.zshrc:eval "$(/path/to/mise activate zsh)"
-
Start a new Claude Code session (creates shell snapshot at
~/.claude/shell-snapshots/) -
Run any command that doesn't exist to trigger
command_not_found_handler:some_nonexistent_command_12345
-
Observe the error above
Root cause verification:
# Check that the snapshot is missing the declaration:
grep -n "typeset -gA _mise_cnf_tried" ~/.claude/shell-snapshots/snapshot-zsh-*.sh
# Returns nothing
# But the function that uses it IS captured:
grep -n "command_not_found_handler" ~/.claude/shell-snapshots/snapshot-zsh-*.sh
# Returns the function definitionClaude Model
Opus
Is this a regression?
I don't know
Claude Code Version
1.0.17 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2 or alacritty or kitty | zellij | zsh
Additional Information
Impact: This affects any tool using associative arrays in shell functions (mise, asdf, custom frameworks, etc.). Developers with multiple environment tools (nix, devbox, mise) are especially affected.
Current Workaround: Manually patch each snapshot file by adding the missing declarations before command_not_found_handler():
typeset -gA _mise_cnf_tried
_mise_fallback() {
local _cmd="$1"; shift
if typeset -f _command_not_found_handler >/dev/null; then
_command_not_found_handler "$_cmd" "$@"
return $?
else
print -u2 -- "zsh: command not found: $_cmd"
return 127
fi
}This requires manually editing ~/.claude/shell-snapshots/snapshot-zsh-*.sh after each regeneration.
Design consideration: The snapshot optimization saves ~200-500ms per command but creates correctness issues. The time to load .zshrc has no token cost - it's just wall-clock time. However, debugging snapshot issues consumes thousands of tokens. A setting like shell.useSnapshots: false would let users with complex shell setups opt for correctness over speed.
Note: Adding typeset -gA _mise_cnf_tried to .zshrc before mise activation doesn't help - the declaration still isn't captured in the snapshot.