alias mise='nocorrect mise' を設定したあとに eval "$(mise activate zsh)" を実行すると、こんなエラーが出ることがあります。
(eval):7: defining function based on alias 'mise'
原因は nocorrect alias と eval によるシェル関数定義の衝突。CORRECT_IGNORE を使うと解決します。
何が起きていたか
zsh の setopt CORRECT はタイポを指摘してくれる便利な機能なんですが、mise みたいなコマンドにも誤検知してくる。
それを黙らせるためによく紹介されているのが alias mise='nocorrect mise' という書き方です。dotfiles のテンプレートやブログ記事にもよく載っていて、自分もそれをそのまま使ってたんですよ。
で、mise のシェル統合を有効にしようとして eval "$(mise activate zsh)" を実行したら、冒頭のエラーが出た。
原因:alias と function の名前衝突
mise activate zsh が出力するコードには、こういうシェル関数の定義が含まれています。
mise() {
local command="${1:-}"
...
command mise "$@"
}
この mise() をパースしようとしたとき、zsh が「あ、mise って alias で登録されてるじゃないか」と検出してパースエラーにする。
zsh 5.4.1 で ALIAS_FUNC_DEF というオプションが導入されて、デフォルト無効(alias と同名の function 定義は禁止)になりました。それ以前のバージョンでは通っていたのに、バージョンアップ後に突然壊れるというパターンも起きます。
処理の流れを整理するとこうなります。
1. .zshrc で alias mise='nocorrect mise' を定義
→ zsh の alias テーブルに 'mise' が登録される
2. eval "$(mise activate zsh)" を実行
→ 出力に mise() { ... } が含まれる
3. zsh パーサーが mise() { ... } を解析
→ 'mise' が alias テーブルに存在するのを検出
→ ALIAS_FUNC_DEF が無効(デフォルト)
→ パースエラー: "defining function based on alias 'mise'"
犯人は alias 側だった
エラーメッセージが "defining function based on alias" なので、一瞬「function の定義がおかしいのか?」と読んでしまうんですが、問題は function 側ではなく alias 側にあります。
eval が展開するコード(mise activate が生成したもの)は正しい。悪いのは事前に alias テーブルを汚染していた nocorrect alias の方。
解決:CORRECT_IGNORE を使う
alias を使わず、zsh の CORRECT_IGNORE パラメータでスペル修正の除外対象を指定します。
# option.zsh setopt CORRECT CORRECT_IGNORE='mise'
CORRECT_IGNORE は glob パターンを受け付けるので、複数ツールをまとめて除外したい場合は zsh の alternation パターンで書けます。
CORRECT_IGNORE='(mise|terraform|kubectl)'
alias を経由しないので、eval 系の function 定義と一切衝突しません。
mise だけじゃない
eval でコマンドと同名のシェル関数を定義するツール全般で同じことが起きます。
| ツール | 初期化コマンド | 定義される関数 |
|---|---|---|
| mise | eval "$(mise activate zsh)" |
mise() |
| rbenv | eval "$(rbenv init -)" |
rbenv() |
| pyenv | eval "$(pyenv init -)" |
pyenv() |
zoxide は z() / zi() を定義するので、alias zoxide='nocorrect zoxide' があっても衝突しません。ただし alias z='nocorrect z' があれば同じ問題が起きます。
nocorrect alias を設定しているツール名と、eval 内で定義される関数名が一致するとき、という条件が揃うと再現します。
なぜ気づきにくいか
dotfiles のテンプレートや古いブログ記事で nocorrect alias が広く紹介されているため、「これが正しい方法」として広まっています。
eval 系ツールを使うまでは問題が顕在化しない。動いている間は正しいと思い込む状態が長く続くので、エラーが出たときに原因の候補に挙がりにくい。
alias 定義と eval 実行が .zshrc 内で離れた位置にあることも多く、原因と結果の距離が遠いのも厄介なところです。
まとめ
nocorrect alias でスペル修正を抑止する方法は広く紹介されているけど、eval 系ツールと名前衝突する構造的な問題があります。CORRECT_IGNORE を使えば alias を介さずに除外できるので、衝突の余地がそもそもなくなります。
エラーメッセージの "defining function based on alias" は function 側ではなく alias 側を疑うサインです。