コンテンツにスキップ

トラブルシューティング

pyfltr運用中に発生しがちな事象と対処法を症状別にまとめる。 導入手順ははじめにを参照。

MCP起動時のstdout占有事故

pyfltr mcp起動後に他のコマンド出力やlogが端末に表示されず、 コーディングエージェントに返る結果が文字化けするまたは解析エラーになる場合がある。

pyfltr mcpを起動するとstdin/stdoutがJSON-RPCフレームに専有される。 同一プロセスや同一パイプライン内で他のテキスト出力が混入すると、 JSON-RPCパーサーがフレームを正しく解析できない。

回避策。

  • pyfltr mcpは単独プロセスとして起動し、他のコマンドとパイプで繋がない
  • コーディングエージェントのMCP設定ではcommanduvxを指定し、 ラッパースクリプトを経由する場合はstdoutに余分な出力が混入しないことを確認する
  • デバッグ目的でlogを確認したい場合はstderrにリダイレクトする (pyfltrはtextout・system logを常にstderrに出力するため、stderrは参照できる)

MCPクライアントでツール認証に失敗する

MCPクライアントからpyfltr mcpを登録してもrun_for_agent等のツール呼び出しでエラーになる場合がある。

確認手順。

  • pyfltrを最新版へ更新する。古いMCPプロトコルバージョンでは互換性問題が発生する場合がある
  • commandに絶対パスではなくuvxを使い、シェル解決に依存させない
  • クライアント側のMCPサーバーログ(Claude Codeであれば設定UIから確認可能)でJSON-RPCエラーの詳細を確認する
  • stdoutに非JSON出力が混じっていないかをstderrへリダイレクトして確認する (uvx pyfltr mcp 2>/tmp/pyfltr-mcp.errのように手動起動して観察できる)

pre-commit統合時の自動スキップ

pre-commitからpyfltrを呼び出しているのに、一部のツールが実行されないことがある。 これはpre-commit経由起動時の意図的なフィルタリング動作である。

pyfltrはpre-commitから呼び出されたことを環境変数PRE_COMMIT=1で検出する。 PRE_COMMIT=1が設定されている場合、pyfltr fastサブコマンドは{command}-fast = trueのツールのみを対象として実行する。 runサブコマンドは自動スキップを行わないため、fastを指定している場合は意図した動作となる。

確認方法。

  • pre-commitのentry設定がpyfltr fastになっているか確認する
  • {command}-fastの設定をpyproject.tomlで確認する (既定では重いツール、mypy・pylint・pytestなどはfastに含まれない)
  • pyfltr fast --verboseで実行対象コマンドの一覧を確認する

逆方向として、make test等からpyfltr runを呼び出した場合は、pyfltr側がSKIP=pyfltr付きで pre-commit runを変更ファイル指定(--files <対象>)で起動して二重実行を避ける。 この自動連携を抑止したい場合はpre-commit-auto-skip = falseを設定する。

既定設定では--filesで対象ファイルを渡して起動するため、 引数なしのpre-commit runが行う未ステージ変更の退避・復元(git stash相当の作業ツリー操作)は発生しない。 対象ファイルが0件の場合はpre-commit自体を起動しない。

--changed-sinceで対象ファイルが空になる場合

--changed-since <REF>を指定したのに実行対象が0件になることがある。

考えられる原因と確認手順は以下のとおり。

  1. 指定した<REF>との間に差分がない場合。 git diff --name-only <REF>のコミット差分・trackedファイルの作業ツリー差分・staged差分の和集合と ファイル展開の時点で残ったファイルリストとの交差が空集合になる。 git diff --name-only <REF>を直接実行して変更ファイルの一覧を確認する。
  2. 対象ファイルがexclude.gitignoreで除外されている場合。 ファイル展開の時点で除外されたファイルは--changed-sinceフィルタの前段で既にリストから除外される。 --no-exclude--no-gitignoreを付けて確認できる。
  3. <REF>にtrackedファイルの作業ツリー差分・staged差分だけを含めたい場合。 --changed-since=HEADHEADとの差分(trackedファイルの作業ツリー差分とstaged差分)を対象とする。 HEADを含む過去コミットとの比較をしたい場合はHEAD~1や具体的なコミットハッシュを指定する。 なお、untrackedの新規ファイル(git add未実施)はgit diffの出力に含まれないため対象外となる。

gitが不在またはrefが存在しない場合は警告を出力して全体実行へフォールバックする。 pyfltr run --verbose --changed-since=<REF>を実行すると警告メッセージを確認できる。

--only-failedが想定どおり動かない場合

--only-failedで再実行しているのに失敗ツールが拾われない、または全体実行になることがある。

主な原因と対処。

  • 直前runのアーカイブが残っていない(--no-archiveまたはarchive = falseで記録されなかった)。 通常実行に戻して再度--only-failedを試す
  • 直前runで失敗ツールが0件だった。pyfltr show-run latestでそのrunのステータスを確認する
  • 位置引数(targets)と直前runの失敗ファイル集合の交差が空になっている。 位置引数を外す、または対象ディレクトリを広げる
  • pass-filenames=Falseのツール(tsc・cargo-*・dotnet-*等)で全体失敗のみだった場合、診断ファイルが 取得できないため既定対象でフォールバック実行する。これは仕様である
  • --from-run <RUN_ID>に存在しないrunを指定した場合は警告を出力してrc=0で早期終了する。 pyfltr list-runsで実在のrun_idを確認する

補足。--only-failedはファイル変更検出・テスト関数の存在確認・モジュール依存追跡を行わない。 判定基準は直前runの診断ファイル一覧と現在のtargets集合の交差のみで、ファイル変更ベースのフィルタリングは--changed-sinceとの併用で実現する。 ツール単位でstatus=skipped, files=0を観測した場合はpyfltr show-run latestで当該ツールの診断ファイル有無を確認する。 診断ファイルなしの場合はフォールバック実行が対象globsに一致せず、対象ファイル0件で終了する。 診断ファイルありの場合はツール単位のINFOログを次の例の形式で出力するため、除外理由を判定できる。

--only-failed: <tool>: 直前 run の失敗ファイル N 件は指定 targets と交差しません。本ツールは対象から除外します。

mise関連のトラブル

bin-runner = "mise"(既定)でcargo系・dotnet系・shellcheck等のツール実行が失敗する場合の対処。

mise.toml未信頼で失敗する

worktreeやdotfiles配下ではmise.tomlが未信頼扱いとなりmise execが失敗することがある。

  • 既定ではmise-auto-trust = truemise trust --yes --allを自動実行する。 --allはcwdおよび親ディレクトリ全configを信頼するため、プロジェクト外のmise.tomlも対象になる点に注意
  • 自動信頼を無効化したい場合はmise-auto-trust = falseを設定し、手動でmise trustを実行する

mise installが失敗する

ネットワーク制約・プラットフォーム未対応などでmise installが失敗する場合がある。

  • mise installを手動で実行してエラー内容を確認する
  • 該当ツールに{command}-runner = "direct"を設定してPATH直接実行へ戻す
  • バージョン指定({command}-version)を変更して入手可能なバージョンを使う

bin-runner = "mise"でもdirectで起動される

bin-runner = "mise"にしているのにpyfltr command-infoeffective_runnerdirectになることがある。 これは「miseバイナリがPATH上に存在しない場合のみ」発火する救済挙動で仕様どおり。 mise本体を導入すれば自動的にmise経由起動へ切り替わる。

mise本体は存在するがmise execが失敗する場合(バージョン解決失敗・config未信頼など)は directにフォールバックせずfailedとして扱う。

pyfltr command-info <tool>での確認

ツールがどの経路で起動されるかはpyfltr command-info <tool>で確認できる。 runner / effective_runner / executable / commandlineを見れば、{command}-runner設定や グローバルbin-runnerの効果が想定どおりかが分かる。 --checkオプションを付けるとmise exec --versionの事前チェック(mise installが起動する場合あり)まで実施する。

PATHが重複していてmiseのtools解決が有効にならない

mise execが想定外の経路でツール解決する場合は次を試す。

  • mise --versionでmise本体が更新済みか確認する
  • pyfltr command-info <tool> --checkで実際の起動コマンドラインを観察する
  • ユーザーシェル設定でPATHmise/installs/配下を直接追加していないか確認する

uvx pyfltr単独実行時にpylintのimport-errorが出る

uvx pyfltr単発で実行した場合、cwdにuv.lockがある環境では 利用者プロジェクトのvenv経由で起動されるため、pylintがimport-errorを発行するケースがある。

対処は次のいずれかを選ぶ。

  • 利用者プロジェクトのdev依存にpyfltr本体を加える(推奨)。 uv add --dev "pyfltr[python]"を実行してuv run pyfltr ...で呼び出す
  • もしくはpylint-runner = "direct"pyproject.toml[tool.pyfltr]配下に明示する

呼び出し方の使い分けと推奨理由は呼び出し方の使い分けを参照。

実行アーカイブのディスク使用量確認(定期管理)

pyfltrは各実行の結果をユーザーキャッシュ配下にアーカイブとして保存する。 長期間使用するとディスク使用量が増加する場合があるため、定期的な確認手順を以下に示す。

pyfltr list-runsで実行アーカイブの一覧を確認できる。

# 直近20件を一覧表示(既定)
pyfltr list-runs

# 件数を増やして確認
pyfltr list-runs --limit=100

# JSONL形式で詳細確認
pyfltr list-runs --output-format=jsonl

一覧にはRUN_IDSTARTED_ATEXITFILESCOMMANDSが表示される。 アーカイブが存在しない環境では(no runs)を出力する。

アーカイブの実体は次の場所に保存される。

OS 保存先
Linux ~/.cache/pyfltr/
macOS ~/Library/Caches/pyfltr/
Windows %LOCALAPPDATA%\pyfltr\Cache

手動で削除する場合はそのディレクトリを対象にする。

アーカイブを無効化する場合は--no-archiveオプションまたは pyproject.tomlarchive = false設定を使う。

設定キーのtypoと未知キー

pyproject.toml[tool.pyfltr]に未知の設定キーを書いた場合、 pyfltrは原因と対処を1つのエラーメッセージにまとめて返す。

設定キー `lychee` は認識できません。もしかして: lychee-args, lychee-runner, lychee-fast。
有効なキー一覧は `pyfltr config list --all` で確認できます

対処方法。

  • 表示されたサジェストの中に意図したキーがあればそれへ書き換える
  • サジェストが無い場合はpyfltr config list --allで全キー一覧を確認する。 当該一覧上で(default)の注記が付くキーは既定値で動作中であり、上書きしたい場合のみpyproject.tomlへ追記する
  • global設定(~/.config/pyfltr/config.toml)の未知キーはValueErrorではなく警告で無視される。 古いpyfltrで新版設定を読み込んでも停止させないための前方互換の挙動である

v3.0.0で削除されたツール(pyupgrade・autoflake・isort・black・pflake8)の 設定キーを残している場合は移行案内付きのValueErrorで停止する。 ruffへ統合済みのため当該設定をすべて削除する。

ツール解決失敗時の対処

pyfltr run実行時にresolution_failed扱いで停止する場合、ツールカテゴリ別に対処を選ぶ。

Python系ツール(mypy・pylint・pyright・ty・pytest・ruff-format・ruff-check・uv-sort・semgrep・sqlfluff・bandit)

メッセージ例。

ツールが見つかりません: Python系ツール `mypy` が PATH 上にありません。
`mypy-runner = "uv"`(cwdに uv.lock が必要、`uv add --dev "pyfltr[python]"` で依存追加)
または `mypy-runner = "uvx"` への切り替え、もしくは `mypy-path` で実行ファイルを明示してください

対処方法。

  • {command}-runner = "uv"へ切り替える。 プロジェクト直下にuv.lockが必要で、uv add --dev "pyfltr[python]"で依存追加する
  • {command}-runner = "uvx"へ切り替える。 PyPI最新版をその都度取得する(uv.lockは参照せず、再現性は犠牲になる)
  • {command}-path = "/path/to/bin"で実行ファイルを直接指定する

JS系ツール(textlint・markdownlint・eslint・biome・oxlint・prettier・tsc・vitest・designmd)

メッセージ例。

js-runner=direct で `textlint` がローカル node_modules に見つかりません
(探索先: node_modules/.bin/textlint)。`pnpm install` などで対象パッケージを導入するか、
`js-runner = "pnpx"` でグローバルキャッシュ経由に切り替えてください

対処方法。

  • pnpm install等でローカルnode_modulesへ対象パッケージを導入する
  • js-runner = "pnpx"へ切り替えてpnpmグローバルキャッシュ経由で起動する。 この経路はnode_modulesを必要としない
  • {command}-path = "..."で実行ファイルを直接指定する

ネイティブ系ツール(shellcheck・shfmt・cargo-・dotnet-・lychee・taplo・hadolint等)

メッセージ例。

ツールが見つかりません: `cargo-clippy` が解決できません。
`cargo-clippy-runner = "direct"` への切り替えか、
`cargo-clippy-path` で実行ファイルを明示してください

対処方法。

  • mise installで対応ツールを導入する(既定のbin-runner = "mise"経路)
  • {command}-runner = "direct"へ切り替えてPATH上のバイナリを直接実行する
  • {command}-path = "/path/to/bin"で実行ファイルを直接指定する

mise経由で発生する未信頼エラー・registry解決失敗等の追加対処は mise関連のトラブル節を参照。

モノレポでサブプロジェクト分割が想定通り動かない場合

  • サブプロジェクトが検出されない
    • 起点cwd配下に pyproject.toml を1件しか検出していない場合、モノレポモードは適用されない (単一プロジェクトとして従来通り動作)
    • .gitignore に記載されたディレクトリは除外される。検出させたい場合は .gitignore の見直しか subproject-use-gitignore = false の設定で除外を解除する
    • .venvnode_modulestargetbuilddist.git は既定で常に除外する。 除外対象を追加・変更したい場合は subproject-exclude で名前を指定する
  • 特定ツールをサブプロジェクト分割の対象から外したい
    • {command}-subproject-aware = falsepyproject.toml に追加する。 リポジトリ単位で1回だけ起動する形に切り替わる
  • --work-dir 指定時の探索起点
    • --work-dir 適用後のcwdを起点としてサブプロジェクトを検出する。 pyfltr run --work-dir=foo なら foo/ 以下を再帰探索する