How Batch Reports Success and Failure
Batch has no exceptions or try/catch; instead, nearly every command and every executable sets an implicit numeric ERRORLEVEL when it finishes, where 0 conventionally means success and any nonzero value signals some kind of failure. ERRORLEVEL is really a pseudo-variable maintained by cmd.exe, readable via %ERRORLEVEL% or tested directly with IF ERRORLEVEL <n>, and it persists until the next command that explicitly sets it, which means a stray ECHO or IF statement between the risky command and the check can silently clobber the value you meant to inspect. Because of this fragility, disciplined batch authors check ERRORLEVEL immediately after the command that might fail, before running anything else.
Cricket analogy: It is like the on-field umpire's raised finger right after a run-out appeal — if you wait even one delivery before consulting it, the moment (and clarity of that specific decision) has already passed and been overwritten by the next play.
Testing ERRORLEVEL and Exit Codes
IF ERRORLEVEL 1 evaluates true if the last ERRORLEVEL is greater than or equal to 1, not merely equal to 1, which surprises programmers coming from languages with strict equality checks; testing IF %ERRORLEVEL% EQU 1 is stricter and usually the clearer, more maintainable form in modern scripts. External programs and your own subroutines set ERRORLEVEL via their process exit code, which in batch you control explicitly with EXIT /B <code>, letting you define a small convention like 0 for success, 1 for missing input, and 2 for invalid configuration so calling scripts can branch on specific failure categories rather than a single generic error flag.
Cricket analogy: IF ERRORLEVEL 1 being 'greater than or equal to' is like a rain-rule threshold in the DLS method that triggers at 20 or more overs bowled, not exactly 20 — any value above the line still counts as crossing it.
@echo off
copy source.txt destination.txt
IF %ERRORLEVEL% NEQ 0 (
echo Copy failed with code %ERRORLEVEL%
EXIT /B 1
)
echo Copy succeeded.
Structuring Error Handling with GOTO :error
Since batch has no try/catch block, a common pattern is to route every failure path to a single labeled section, typically :error, using a chain of IF %ERRORLEVEL% NEQ 0 GOTO :error checks after each risky command, so cleanup and logging logic lives in exactly one place instead of being duplicated after every command. Inside :error you can echo a diagnostic message, write to a log file with an appended timestamp, and finish with EXIT /B 1 so the calling process or scheduler (like Task Scheduler or a CI pipeline) sees a nonzero exit code and can react accordingly. This centralization also makes it far easier to add consistent behavior later, such as sending an alert, without touching every individual command site.
Cricket analogy: It is like a team having one designated review-referral protocol that every fielder funnels doubtful decisions through, rather than each fielder independently deciding when and how to challenge an umpire's call.
A minimal but effective convention: after every command that can fail, add IF %ERRORLEVEL% NEQ 0 GOTO :error on the very next line, and place a single :error label near the bottom of the script that logs %ERRORLEVEL%, the failing step name, and exits with EXIT /B 1.
PowerShell and some GUI tools return 0 even when they failed silently, and some command-line tools don't set ERRORLEVEL at all for certain warning conditions — always test your error-handling chain against real failure scenarios rather than assuming every tool follows the 0-means-success convention correctly.
- Batch has no exceptions; failure detection relies entirely on the numeric ERRORLEVEL set after each command.
- IF ERRORLEVEL 1 tests 'greater than or equal to 1'; use IF %ERRORLEVEL% EQU 1 for exact matching.
- Check ERRORLEVEL immediately after the risky command, since the next command can overwrite it.
- EXIT /B <code> lets your own subroutines and scripts set a custom, meaningful exit code.
- A GOTO :error pattern centralizes logging and cleanup for every failure path in one place.
- Nonzero exit codes let callers like Task Scheduler or CI pipelines detect and react to failures.
- Not all tools reliably set ERRORLEVEL on failure, so error-handling chains must be tested against real tools.
Practice what you learned
1. What does a nonzero ERRORLEVEL conventionally indicate after a command runs?
2. What is a key difference between IF ERRORLEVEL 1 and IF %ERRORLEVEL% EQU 1?
3. Why should ERRORLEVEL be checked immediately after the command that might fail?
4. What does the GOTO :error pattern accomplish in a batch script?
5. How does a script set a custom exit code for callers like Task Scheduler to detect?
Was this page helpful?
You May Also Like
Batch Script Functions with CALL
Learn how to simulate reusable functions in Windows Batch using labeled subroutines invoked with CALL, including parameter passing and local variable scope.
Environment Variables in Batch
Understand how Windows Batch scripts create, read, scope, and persist environment variables, including the tricky topic of delayed expansion.
Batch Script Arguments
Learn how Windows Batch scripts read command-line arguments using positional parameters, SHIFT, and path modifiers like %~dp0.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics
Microsoft TechnologiesMVVM Design Pattern Study Notes
.NET · 30 topics