22

Intro

There's a lot of advice out there for dealing with return codes in batch files (using the ERROLEVEL mechanism), e.g.

Some of the advice is to do if errorlevel 1 goto somethingbad, while others recommend using the %ERRORLEVEL% variable and using ==, EQU, LSS, etc. There seem to be issues within IF statements and such, so then delayedexpansion is encouraged, but it seems to come with quirks of its own.

Question

What is a foolproof (i.e. robust, so it will work on nearly any system with nearly any return code) way to know if a bad (nonzero) code has been returned?

My attempt

For basic usage, the following seems to work ok to catch any nonzero return code:

if not errorlevel 0 (
    echo error level was nonzero
)
Community
  • 1
  • 1
Pat
  • 16,515
  • 15
  • 95
  • 114

1 Answers1

47

Sorry, your attempt is not even close. if not errorlevel 0 is only true if errorlevel is negative.

If you know that errorlevel will never be negative, then

if errorlevel 1 (echo error level is greater than 0)

If you must allow for negative errorlevel, and are not within a parenthesized block of code, then

set "errorlevel=1"
set "errorlevel="
if %errorlevel% neq 0 (echo error level is non-zero)

Note - I edited my answer to explicitly clear any user defined errorlevel value after reading Joey's comment to the linked answer in the question. A user defined errorlevel can mask the dynamic value that we are trying to access. But this only works if your script has a .bat extension. Scripts with .cmd extension will set your ERRORLEVEL to 0 if you set or clear a variable! To make matters worse, XP will set ERRORLEVEL to 1 if you attempt to undefine a variable that does not exist. That is why I first explicitly define an ERRORLEVEL variable before I attempt to clear it!

If you are within a parenthesized block of code then you must use delayed expansion to get the current value

setlocal enableDelayedExpansion
(
  SomeCommandThatMightGenerateAnError
  set "errorlevel=1"
  set "errorlevel="
  if !errorlevel! neq 0 (echo error level is non-zero)
)

But sometimes you don't want delayed expansion enabled. All is not lost if you want to check the error level immediately after executing a command.

(
  SomeCommandThatMightGenerateAnError && (echo Success, no error) || (echo There was an error)
)

If you absolutely must check the dynamic ERRORLEVEL value without using delayed expansion within a parenthesized block, then the following works. But it has the error handling code in two places.

(
  SomeCommandThatMightGenerateAnError
  if errorlevel 1 (echo errorlevel is non-zero) else if not errorlevel 0 (echo errorlevel is non-zero)
)


Here, at long last, is the "ultimate" test for non-zero errrolevel that should work under any circumstances :-)

(
  SomeCommandThatMightGenerateAnError
  set foundErr=1
  if errorlevel 0 if not errorlevel 1 set "foundErr="
  if defined foundErr echo errorlevel is non-zero
)

It can even be converted into a macro for ease of use:

set "ifErr=set foundErr=1&(if errorlevel 0 if not errorlevel 1 set foundErr=)&if defined foundErr"
(
  SomeCommandThatMightGenerateAnError
  %ifErr% echo errorlevel is non-zero
)

The macro supports parentheses and ELSE just fine:

%ifErr% (
  echo errorlevel is non-zero
) else (
  echo errorlevel is zero
)


One last issue:

Redirection of input and/or output can fail for any number of reasons. But redirection errors do not set the errorlevel unless the || operator is used. See File redirection in Windows and %errorlevel% for more information. So one can argue that there does not exist a fool-proof way to check for errors via errorlevel. The most reliable method (but still not infallible) is the || operator.

Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • 4
    It's worth noting that errorlevel is [not an environment variable](http://blogs.msdn.com/b/oldnewthing/archive/2008/09/26/8965755.aspx). – Nick Westgate Jun 15 '15 at 01:07
  • 1
    @NickWestgate - Yep, ERRORLEVEL is one of many "pseudo" or "dynamic" variables. I have identified and documented three classes of "dynamic" variables at http://stackoverflow.com/a/20169219/1012053, and within that post I reference that same Raymond Chen blog. – dbenham Jun 15 '15 at 01:47
  • 1
    EDIT 2016-06-03: I modified the code to clear any user defined ERRORLEVEL to account for XP behavior that sets ERRORLEVEL to 1 if you attempt to undefine a non existent variable. – dbenham Jun 03 '16 at 21:44
  • Stumbled across your answer while searching for checking for non zero error code. (Am converting a short shell script to run something on windows) It is astonishing that something which can be done simply in a shell script with var=$?; if [ $var -ne 0 ] then #Do something is so complicated and unintuitive in batch files. – ranban282 Feb 19 '22 at 06:35