Runtime Error 20: “Resume without error,” explained and fixed

Error 20, “Resume without error”, means a Resume or Resume Next executed when VBA was not actually handling an error. Resume is only legal inside an active error handler; when execution wanders into the handler without an error occurring, the first Resume it meets raises error 20. Like error 3, it is a control-flow structure bug, and the trigger is almost always a missing Exit Sub before the handler label.

For people who just run the program

  1. Expect it after the macro seemed to succeed. The work often completes, then the error appears at the very end, because flow ran on into the handler after finishing the real code.
  2. Note whether the results look correct. If the output is right and only the ending errors, tell the maintainer; it confirms the handler is being entered by fall-through.
  3. Do not rerun hoping it clears. A structural fall-through repeats identically every run.
  4. Send the error number and the macro name. The fix is one line in the code, and this number identifies it precisely.

For people who write the code

  1. Put Exit Sub (or Exit Function) immediately before the handler label. This is the cause in the overwhelming majority of cases:
  2. Sub Import()
        On Error GoTo Handler
        ' ... work ...
        Exit Sub            ' without this, success falls into the handler
    Handler:
        MsgBox Err.Description
        Resume Next         ' error 20: no error is active on fall-through
    End Sub
  3. Never call the handler as if it were a subroutine. A GoTo into the handler from normal code produces the same problem; handlers are entered only by the error mechanism.
  4. After fixing the layout, ask why the code was written that way. Fall-through handlers usually mean cleanup code was meant to run on both paths. Move shared cleanup into its own procedure and call it from both the success path and the handler.
Error 20 masks the real code. Because it fires inside the handler, people often “fix” the handler itself. The handler is fine; the missing exit above it is the bug. Change the layout, not the Resume.

If it still happens

If the layout is correct and error 20 still appears, look for a Resume executed after Err.Clear was called in the same handler, or a nested call: the procedure was invoked from another handler, completed, and the Resume in the outer code then has no active error of its own. Trace the call stack when it fires.

Common questions

What is the difference between error 3 and error 20? Both are fall-through bugs. Error 3 is a Return reached without a GoSub; error 20 is a Resume reached without an active error. Both are fixed by controlling flow into the block, usually with Exit Sub.

Can Resume Next at the top of a procedure cause error 20? On Error Resume Next is a directive, not the Resume statement, and cannot raise error 20. Only an executed Resume or Resume label statement outside an active handler does.

Related errors

Runtime Error 3 · Runtime Error 35 · Runtime Error 5