バッチファイルを実行すると、どの処理を通っても ERRORLEVEL が常に 1 になってしまい、正常系と異常系の判定がまったく機能しないという状況に遭遇することがあります。
この現象は珍しいものではなく、多くの場合は「エラーが起きている」のではなく、ERRORLEVEL の参照対象や更新タイミングを誤っていることが原因です。
ここでは、ERRORLEVEL が常に 1 になってしまうときに、上から順に確認すべきチェックポイントを、実務での切り分け順を意識して整理します。
ERRORLEVELの基本から確認したい場合は、ERRORLEVELを使ってエラーハンドリングを行う方法も参考にしてください。
本当に失敗しているコマンドが含まれていないか
最初に確認すべきなのは、実行しているコマンド自体が失敗扱いになっていないかどうかです。
find や findstr、fc などの検索・比較系コマンドは、処理自体は成功していても条件不一致だけで ERRORLEVEL に 1 を設定します。
この挙動を知らずに使っていると、常にエラーが発生しているように見えます。
find "ABC" sample.txt > nul
echo %ERRORLEVEL%
検索対象が存在しないだけでも ERRORLEVEL は 1 になります。
ERRORLEVEL を更新しないコマンドを挟んでいないか
echo や set、rem のようなコマンドは ERRORLEVEL を変更しません。
そのため、過去に 1 が設定された状態のまま、ERRORLEVEL が更新されずに残り続けることがあります。
この状態で if ERRORLEVEL を評価すると、原因のないエラーが続いているように見えます。
判定の直前に、余計なコマンドを挟んでいないかを確認してください。
判定対象のコマンドと距離が空いていないか
ERRORLEVEL は「直前に実行されたコマンド」の結果です。
対象コマンドの直後ではなく、数行後で判定している場合、まったく別のコマンドの ERRORLEVEL を見ている可能性があります。
somecommand
echo 処理中
if errorlevel 1 echo エラー
この場合、判定対象は somecommand ではなく echo になります。
パイプ処理の最後のコマンドが原因になっていないか
パイプ(|)を使った場合、ERRORLEVEL は最後に実行されたコマンドの終了コードになります。
前段が成功していても、後段が条件不一致扱いになるコマンドだと ERRORLEVEL は 1 になります。
type sample.txt | find "ABC" > nul
このケースでは find が見つからなかっただけで 1 になります。
処理全体の成否判定として使うなら、パイプを分解して判定する必要があります。
if ERRORLEVEL の仕様を誤解していないか
if ERRORLEVEL は「等号比較」ではなく、指定値以上かどうかを判定します。
ERRORLEVEL が 1 のとき、if ERRORLEVEL 0 は常に真になります。
結果として、エラー状態が解除されていないように見えることがあります。
括弧ブロック内で%ERRORLEVEL%を使っていないか
括弧ブロック内で %ERRORLEVEL% を参照すると、値がパース時に固定され、常に同じ値に見えることがあります。
これにより、処理結果に関係なく ERRORLEVEL が 1 のままに見えるケースがあります。
この場合は、遅延環境変数展開を有効にして !ERRORLEVEL! を使う必要があります。
setlocal enabledelayedexpansion
somecommand
if !ERRORLEVEL! neq 0 (
echo エラー
)
robocopyなど特殊な終了コードを返すコマンドを使っていないか
robocopy のように、ERRORLEVEL の数値そのものに意味を持たせているコマンドもあります。
この場合、0 以外が必ずしもエラーではありません。
仕様を知らずに「0 以外=失敗」と判断すると、常に ERRORLEVEL が 1 以上に見える状態になります。
ERRORLEVELを意図せず引き継いでいないか
サブルーチンや call を使って処理を分割している場合、呼び出し元に ERRORLEVEL が引き継がれます。
戻り値を設計していないと、以前のエラーコードが残ったままになることがあります。
サブルーチンの出口で exit /b 0 などを明示する設計が必要です。
どうしても切り分けたいときの最終確認
原因が分からない場合は、成功が保証されているコマンドで ERRORLEVEL を一度 0 に戻し、その後の変化を確認します。
cmd /c exit 0
echo %ERRORLEVEL%
ここで 0 にならない場合、環境や構文自体に問題がある可能性が高くなります。
まとめ
ERRORLEVEL が常に 1 になるときは、処理が失敗しているとは限らず、参照対象・更新タイミング・コマンド仕様のどれかを誤っているケースがほとんどです。
直前に何を実行したのか、そのコマンドはどんな終了コードを返す仕様なのかを一つずつ確認していけば、必ず原因にたどり着けます。
チェックリストとして順に潰していくことで、ERRORLEVEL が「信頼できる判定材料」として使える状態に戻せます。
