# Getting ROBOCOPY to return a "proper" exit code?

Is it possible to ask ROBOCOPY to exit with an exit code that indicates success or failure?

I am using ROBOCOPY as part of my TeamCity build configurations, and having to add a step to just silence the exit code from ROBOCOPY seems silly to me.

EXIT /B 0


to the script that is being run.

However, this of course masks any real problems that ROBOCOPY would return.

Basically, I would like to have exit codes of 0 for SUCCESS and non-zero for FAILURE instead of the bit-mask that ROBOCOPY returns now.

Or, if I can't have that, is there a simple sequence of batch commands that would translate the bit-mask of ROBOCOPY to a similar value?

As per here, Robocopy has the following exit code bits that make up the exit code:

0×10 Serious error. Robocopy did not copy any files. This is either a usage error or an error due to insufficient access privileges on the source or destination directories.

0×08 Some files or directories could not be copied (copy errors occurred and the retry limit was exceeded). Check these errors further.

0×04 Some Mismatched files or directories were detected. Examine the output log. Housekeeping is probably necessary.

0×02 Some Extra files or directories were detected. Examine the output log. Some housekeeping may be needed.

0×01 One or more files were copied successfully (that is, new files have arrived).

0×00 No errors occurred, and no copying was done. The source and destination directory trees are completely synchronized.

Just add if/else statements that EXIT /B 0 when the return value is 1 or maybe 0, and EXIT /B 1 otherwise. Even if files might have been copied, there's something wrong that would need manual intervention.

TechNet suggests this one-liner to convert the exit code into a more traditional exit code:

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LEQ 1 exit 0


Or this to ignore the exit code completely (i.e. don't care if it failed or succeeded):

(robocopy c:\dirA c:\dirB *.*) ^& exit 0


However, both commands above will terminate a script after the robocopy has executed. This is an issue especially for CI builds. If you want to use robocopy in this scenario, you need to set the error code manually for irrelevant exit codes. Below, all error codes below 8 will be rewritten to no error at all, and the script will be continued if possible.

(robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LSS 8 SET ERRORLEVEL = 0

• Nice. Needs brackets around the robocopy command, but saved me using a wrapper script. Mar 2, 2012 at 14:59
• I couldn't get this one-liner to work as a Command Line build step in TeamCity. I had to move it to a separate line. I also added the /B argument to the exit command, although I don't think that was required. May 7, 2012 at 17:35
• For Teamcity deployment (and not only Teamcity) it is useful to type: IF %ERRORLEVEL% LEQ 3 set errorlevel=0 and on the next line: if %errorlevel% neq 0 exit /b %errorlevel% (if batch file consists of several operations, not only robocopy), because OK codes are less then 3. ss64.com/nt/robocopy-exit.html Dec 11, 2012 at 13:23
• In TeamCity, you should escape the ERRORLEVEL with double %%, like this: %%ERRORLEVEL%%. Otherwise, it considers it to be TeamCity build parameter. Sep 27, 2013 at 7:09
• What does the ^& do? ss64 says escapes but it seems to me it shouldn't be escaped? May 10, 2017 at 13:40

Running it from Jenkins needs both ( ) and /B. If you want to ignore the error level 1,2,3,4:

(robocopy XXX YYY) ^& IF %ERRORLEVEL% LEQ 4 exit /B 0

• LSS 8 might be even better :)
– Ivan
Jul 16, 2017 at 16:51
• This isn't working for me, and I bet it's because of cmd.exe's early expansion of variables. Other sources I've read say this can only work with delayed expansion. Jan 13, 2021 at 22:10
• Also, & is the wrong operator here. You want ||. (That is, double-check only when robocopy returns nonzero.) Jan 13, 2021 at 22:24
• I don't have enough rep to answer, but here's the actual answer: (Setlocal EnableDelayedExpansion) && (robocopy <...>) || IF !ERRORLEVEL! LSS 8 (cd.) Jan 13, 2021 at 22:26

From this page you can add a section to your batch file that uses the list of error codes to output the errors and run different sections of code:

if %ERRORLEVEL% EQU 16 echo ***FATAL ERROR*** & goto end
if %ERRORLEVEL% EQU 15 echo OKCOPY + FAIL + MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 14 echo FAIL + MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 13 echo OKCOPY + FAIL + MISMATCHES & goto end
if %ERRORLEVEL% EQU 12 echo FAIL + MISMATCHES& goto end
if %ERRORLEVEL% EQU 11 echo OKCOPY + FAIL + XTRA & goto end
if %ERRORLEVEL% EQU 10 echo FAIL + XTRA & goto end
if %ERRORLEVEL% EQU 9 echo OKCOPY + FAIL & goto end
if %ERRORLEVEL% EQU 8 echo FAIL & goto end
if %ERRORLEVEL% EQU 7 echo OKCOPY + MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 6 echo MISMATCHES + XTRA & goto end
if %ERRORLEVEL% EQU 5 echo OKCOPY + MISMATCHES & goto end
if %ERRORLEVEL% EQU 4 echo MISMATCHES & goto end
if %ERRORLEVEL% EQU 3 echo OKCOPY + XTRA & goto end
if %ERRORLEVEL% EQU 2 echo XTRA & goto end
if %ERRORLEVEL% EQU 1 echo OKCOPY & goto end
if %ERRORLEVEL% EQU 0 echo No Change & goto end

:END
REM END OF BATCH FILE


Some posters above have missed the subtlety of the bit mask. In particular paradroid has missed that errorlevel 3 indicates a completely successful copy.

Note that bit 0x01 if set indicates that some files have been copied even if there were other failures. So any odd numbered errorlevels always indicate that at least some files have been copied. Note also that bit 0x02 simply indicates that there are files at the destination that are not present at the source. This will happen if the /E switch is used and files have been deleted from the source since a previous copy was taken. It should not happen if the /MIR switch is used because that should delete files at the destination to mirror the source (but I haven't tested this).

So both errorlevel 1 AND 3 indicate successful copying of files with no errors. Also errorlevels 0 AND 2 indicate that the destination is up to date and no files were copied.

For what its worth I came up with the following for my simple backup:

if errorlevel 16 echo Backup failed - see reason above & goto done

if errorlevel 8 echo All is not well - backup incomplete & goto done

if errorlevel 4 echo All is not well - some files were mismatched & goto done

if errorlevel 3 echo Backup completed successfully & goto done

if errorlevel 2 echo Backup already up to date - no files copied & goto done

if errorlevel 1 echo Backup completed successfully & goto done

if errorlevel 0 echo Backup already up to date - no files copied & goto done


I chose not to bother about the 'extra' files.

I have no idea what the 'mismatched' error is because it hasn't happened yet but I allowed for it just in case.

I use this:

robocopy .....
call :REPORT_ERRORLEVEL
goto :EOF

:REPORT_ERRORLEVEL
echo.
if ERRORLEVEL 16 echo ***FATAL ERROR*** & goto :EOF
if ERRORLEVEL 8 echo **FAILED COPIES** & goto :EOF
if ERRORLEVEL 4 echo *MISMATCHES* & goto :EOF
if ERRORLEVEL 2 echo EXTRA FILES & goto :EOF
if ERRORLEVEL 1 echo Copy successful & goto :EOF
if ERRORLEVEL 0 echo –no change– & goto :EOF


I agree with Guest John - you really only want to indicate an error if the result is actually 8 or higher.

so to map a robocopy result to a 0 (success) or 1 (fail) result, suitable for use in a SQL Agent job, I am using this:

  IF %ERRORLEVEL% LSS 8 EXIT /B 0
EXIT /B 1


For TeamCity I'm using this and it's working quite well. Thanks to input from MikeWyatt, DaoCacao, and Yan Sklyarenko. I just needed to see a full working example to help visualize the answer.

(robocopy  .\Artifacts\Fitnesse %FitDestinationFolder% /MIR)
IF %%ERRORLEVEL%% LEQ 3 set errorlevel=0
IF %%ERRORLEVEL%% NEQ 0 EXIT /b %%ERRORLEVEL%%
EXIT 0

• I'm using a similar robocopy script in my POST-BUILD event .. so dependent libraries are copied over into the consuming .exe application project - which are only referenced via inversion-of-control / service locator pattern. Feb 12, 2015 at 18:54

add cmd /c before it for gitlab ci.

cmd /c (robocopy c:\dirA c:\dirB *.*) ^& IF %ERRORLEVEL% LEQ 1 exit 0


otherwise EXIT 0 closes the CI pipeline at that point.

• I had this problem with gitlab too. The PowerShell will write the exit code to the var $lastexitcode as mentioned here So there's no need of using operators anymore: (robocopy E:\test E:\test1 /MIR);if ($lastexitcode -eq 0){write-host "Robocopy succeeded"}else{write-host $lastexitcode}; Nov 13, 2019 at 8:43 An example here on how to copy finished files from Visual Studio 2010+ to another folder as Visual Studio expects a 0 not 1 on a good copy. cmd /c (robocopy$(TargetDir) X:\$(TargetName)$(TargetFileName) \$(TargetFileName).config *.dll *.json *.xml /xx) ^& IF %ERRORLEVEL% LEQ 1 exit 0


I wasn't able to reliably get the versions with %ERRORLEVEL% to be treated as a failure, so this is what I came up with:

cmd /C (robocopy a b) ^& IF NOT ERRORLEVEL 8 (EXIT 0) ELSE (EXIT 1)

All failures get mapped to an error code of 1, otherwise success has code 0.

Any value greater than 8 indicates that there was at least one failure during the copy operation.

Here's how I would do it:

robocopy [...] & if not errorlevel 4 ver > nul


Assuming that extra files are OK, but mismatched files are not, then exit codes 0, 1, 2 and 3 indicate success and all other indicate failure.

(Mismatched meaning we are trying to copy a file, but we can't because there's already a directory with the same name there.)

In batch files/cmd, exit codes set the ERRORLEVEL. To reset the ERRORLEVEL to 0 (success) we can use the fact that ver returns 0 (and discard the output). If it's 4 or greater, we can just leave the ERRORLEVEL unchanged.

Example:

robocopy C:\temp\foo C:\temp\bar test.txt & if not errorlevel 4 ver > nul && echo Copy OK