With the following defaults unchanged:
Zend_Controller_Front::_throwExceptions is false, Zend_Layout::_mvcSuccessfulActionOnly is true, and Zend_Controller_Action_Helper_ViewRenderer and Zend_Controller_Plugin_ErrorHandler are enabled.

This appears to occur because when _throwExceptions is false, the exception thrown by Zend_Controller_Action_Helper_ViewRenderer is caught and Zend_Layout_Controller_Action_Helper_Layout::postDispatch() is allowed to run, setting _isActionControllerSuccessful to true. Therefore the default layout is rendered around the empty content of missingviewscriptAction, then the error layout is rendered around this content and the errorAction content.

The preferred bahavior would be to skip rendering of the layout around the missingviewscriptAction, either by default or through configuration.

The layout helper gets notified first. In Zend_Layout_Controller_Action_Helper_Layout::postDispatch(), $this->_isActionControllerSuccessful is set to true.

The viewrenderer helper gets notified next. In Zend_Controller_Action_Helper_ViewRenderer::postDispatch(), $this->render() is called. This is where the trouble begins - in Philip's example, the view script is not found (thus generating an exception); in my example, the view script is found but it throws an exception.

Control now returns to the front controller (Zend_Controller_Front::dispatch()). The exception is caught, and $this->_response->setExecption() is called. Next, Zend_Controller_Front::dispatch() calls $this->_plugins->postDispatch().

The layout plugin is again notified first. Zend_Layout_Controller_Plugin_Layout::postDispatch() runs, and since isActionControllerSuccessful was set to true earlier, it doesn't return early. An empty layout is rendered.

The errorhandler is notified next. Zend_Controller_Plugin_ErrorHandler::postDispatch() runs, sets a bunch of stuff, forwards to the error controllre, which renders again, causing the second layout and error content to be rendered.

The way I've found to band-aid over the issue is to apply the following patch:

This causes the first run through Zend_Layout_Controller_Plugin_Layout::postDispatch() to return early, because the response already has its exception set, but no error handler has been set yet, since the error handler plugin has not yet run. The second run through Zend_Layout_Controller_Plugin_Layout::postDispatch() renders the layout and the error content, as expected.

There are two problems with this patch that are immediately obvious. First, it doesn't take mvcSuccessfulActionOnly into account. If mvcSuccessfulActionOnly is set to false, this patch will still cause the layout to not render the first time around. Another problem is that the fix is hard-coded to detect behavior of the error handler plugin, which links the two classes together in a way that they probably shouldn't be linked. In particular, if the error handler plugin was disabled, exceptions would never be rendered with a layout. So this patch is not probably not ready to be applied as-is. But I hope it illustrates the problem and makes getting to a real fix easier.

What this allows to happen is that the viewRenderer will run before the Layout action helper and will be able to detect if a view script exception had occured, thus affecting whether or not Zend_Layout can detect if there was a SuccessfulAction.

The real solution which I have been working on is implementing a better stack for the Zend_Controller_Action_HelperBroker. This is turning out to be more than a few line fix, so I think it would be best to use the above workaround in 1.5.x and then I will introduce the HelperBroker_Stack in 1.6 as a new feature.

Having a proper stack will allow Zend_Controller to register the ViewRenderer at a specific predetermined location in the stack, and will also allow Zend_Layout to register its action helper at a predetermined location in the stack. If both can go into known locations, we can ensure that the viewRenderer (And all other future action helpers - system or user), can be assured that they can run before the layout action helper thus - fixing the problem of "unkown state regarding successful action controllers".