Skip to content

fix: stop chezmoi ps1 scripts from loading the PowerShell profile - #126

Merged
torumakabe merged 1 commit into
mainfrom
torumakabe-fix-pwsh-noprofile-and-drop-corepack
Jul 28, 2026
Merged

fix: stop chezmoi ps1 scripts from loading the PowerShell profile#126
torumakabe merged 1 commit into
mainfrom
torumakabe-fix-pwsh-noprofile-and-drop-corepack

Conversation

@torumakabe

Copy link
Copy Markdown
Owner

背景

Windows で chezmoi update を実行すると、次のエラーが 2 回出ていた。

InvalidOperation: Unable to find type [Microsoft.PowerShell.PSConsoleReadLine].

原因は 3 段の連鎖である。

  1. chezmoi は .ps1 を既定の実行系 pwsh -NoLogo -File で実行する。-NoProfile が無いため、スクリプト実行のたびにユーザープロファイルが読まれる
  2. プロファイルの mise activate pwsh が CommandNotFound ハンドラを登録し、その本体が [Microsoft.PowerShell.PSConsoleReadLine]::GetHistoryItems() を参照する
  3. 非対話 pwsh には PSReadLine が読み込まれていないため、スクリプト内でコマンド解決に失敗するたびに InvalidOperation が出る

今回の発火点は run_onchange_after_15-mise-sync-tools.ps1Get-Command -Name 'corepack' だった。corepack が消えていたのは、node の再インストールが node.exe のロックで中断し、削除だけ進んだ環境破損による。

対応

2 層で塞いだ。

発火点の除去(ADR-022): corepack への依存をやめ、pnpm を mise で直接管理する。Node 25 で Corepack の同梱が廃止された(nodejs/node#57617, #59835)ため、いずれ必要だった変更でもある。

  • config.toml.tmplpnpm = "latest" を追加し、lockfile へ 5 プラットフォーム分のエントリを追加
  • run_onchange_after_15-mise-sync-tools.{ps1,sh}.tmpl の corepack 有効化ブロックを削除
  • run_onchange_after_21-link-mise-shims.sh.tmplEXCLUDE_EXACTcorepack から pnpm

構造の是正(ADR-023): .chezmoi.toml.tmpl[interpreters.ps1]pwsh -NoLogo -NoProfile -File に固定する。corepack だけを消しても、スクリプトが未導入コマンドの有無を調べる限り同じ現象は再発するため、プロファイル読み込み自体をやめる。副次的に、chezmoi のスクリプト実行がユーザー環境の副作用(alias、関数、PATH 改変)を持ち込まなくなる。

注意点

  • 適用時に chezmoi init の再実行が必要。config template の変更なので chezmoi update だけでは反映されない
  • プロファイル経由でしか PATH に入らないツールは、chezmoi のスクリプトから解決できなくなる。mise の shim は Machine+User の PATH に永続登録されているため、mise.exe / gh.exe / uv.exe / git.exe が解決することはクリーンな PATH で確認済み
  • 塞げるのは chezmoi 経由の実行だけである。他のツールが pwsh -File でスクリプトを起動する場合、mise のハンドラ問題は依然として発火する(ADR-022 の「引き継ぐ検証」に記録)
  • run_after_40-check-git-hooks.ps1.tmpl にあった「chezmoi は Windows で powershell.exe (5.1) を使う」というコメントは事実誤認だったので、あわせて修正した

検証

  • uv run -m unittest discover -s tests → 304 tests OK (skipped=16)
  • tests/test_chezmoi_config_template.py にソース形状と chezmoi execute-template --init のレンダリング結果を検査するテストを追加
  • レンダリングした config で chezmoi --config <cfg> dump-config を実行し、interpreters.ps1.args["-NoLogo","-NoProfile","-File"] になることを確認
  • クリーンな PATH(Machine+User のみ)で pwsh -NoLogo -NoProfile -File を実行し、未導入コマンドを引いても PSReadLine エラーが出ないことを確認

chezmoi update printed "Unable to find type
[Microsoft.PowerShell.PSConsoleReadLine]" twice on Windows.

chezmoi runs .ps1 with the default `pwsh -NoLogo -File`, which loads the
user profile. The profile activates mise, whose CommandNotFound handler
dereferences a PSReadLine type that a non-interactive pwsh does not have,
so every failed command lookup inside a script raises InvalidOperation.
The trigger was `Get-Command -Name corepack` in the mise sync script.

Two layers of fix:

- Remove the corepack dependency and manage pnpm directly with mise
  (ADR-022). Node 25 stopped bundling Corepack, so this was due anyway.
- Pin the .ps1 interpreter to `pwsh -NoLogo -NoProfile -File` in
  .chezmoi.toml.tmpl (ADR-023) so no future command lookup can trip the
  handler, and so scripts stop inheriting profile side effects.

Applying this requires re-running `chezmoi init` to regenerate the config.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: fb74ae4d-90e8-422e-b537-1cd9e1920e97
@torumakabe
torumakabe merged commit 19590e8 into main Jul 28, 2026
1 check passed
@torumakabe
torumakabe deleted the torumakabe-fix-pwsh-noprofile-and-drop-corepack branch July 29, 2026 13:18
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