Runtime Error 365: “Unable to unload within this context,” explained and fixed

Error 365, “Unable to unload within this context”, means the Unload statement itself was legal but its location was not. Some moments in a form's life cannot tolerate the form being destroyed: inside particular events, while the host is in the middle of its own processing, or from contexts such as a control's paint cycle in classic VB. The object could be unloaded a moment later from a different place; the context, not the object, is the problem. It is a timing bug in the code.

For people who just run the program

  1. This is a developer-facing error. It appears in form-based VB/VBA programs when a window tries to close itself from the wrong place; no user action or document causes it.
  2. Note what the window was doing. Closing itself while loading, while redrawing, or in response to a specific control event are the contexts that matter; the maintainer needs to know which.
  3. Close the window manually if it stays open. A failed unload typically leaves the form on screen; closing it normally is safe and loses nothing.
  4. Report the window and the action that was in progress. Together they identify the forbidden context precisely.

For people who write the code

  1. Defer the unload out of the forbidden context. The standard pattern is to note the request and act on it from a safe point: set a flag in the event, and perform the unload from a timer tick or after the current processing completes:
  2. ' In the event that cannot unload:
    wantsClose = True
    tmrClose.Enabled = True        ' one-shot timer, short interval
    
    ' In the timer, now in a safe context:
    Private Sub tmrClose_Timer()
        tmrClose.Enabled = False
        Unload Me
    End Sub
  3. Respect the classic forbidden moments. In VB6 and VBA forms, unloading from within events such as Paint, Resize in some hosts, or from a control's own event on the same form, is where error 365 lives. If Unload must be conditional on those events, defer it.
  4. Use Hide while deciding. If the goal is to make the window disappear promptly while teardown must wait, Me.Hide now and Unload at the safe point gives the user the right experience without breaking the context rule.
Error 365 is not a state problem like 361 or 364. The object exists and could be unloaded; the call site cannot. Moving the same Unload statement is the entire fix, which is why attempts to change the object's state never help.

If it still happens

If the unload sits in an ordinary button handler and error 365 still fires, the handler may be running inside a host-controlled context: a modeless form driven by an external caller, or code running during the host's own event processing. Log the call stack at the failure; the frames above the handler reveal who owns the context.

Common questions

Why would Unload ever be forbidden? Because destroying a form while the system is inside that form's own event processing leaves the processor with no object to return to. The runtime forbids the unload at those moments rather than crashing.

Is the timer deferral a hack? It is the documented, standard pattern for this situation: it moves the unload to the next safe message-processing point. The alternative designs (flags checked by the caller, Hide plus deferred unload) achieve the same move.

Related errors

Runtime Error 364 · Runtime Error 361 · Runtime Error 400