This is a repost from another topic, but it should answer most of your questions:
If an exception is thrown up the stack and caught by the dispatcher servlet and routed to a error page, the flow execution by default will continue to sit around in the session until the session expires; that is, if you are choosing to persist your flows in the session. The same applies if I start a flow and then go to the bathroom and don't come back for awhile.
With that said, there is a ExpiredFlowCleanupFilter you can install that will automatically detect and cleanup expired/abandoned flows. See the web.xml file of the ItemList sample, which illustrates this.
Also, if you're using a client-continuation based flow execution storage strategy, no cleanup is neccessary as there is no session state.
On the other hand, If you're using a http session continuation based flow execution storage strategy (sellitem does this by default), a new copy of the flow execution is created and stored in the session on each flow request. This is the most expensive strategy in terms of storage, but the most flexible with regards to state restoration (e.g allowing proper back button use--as you can restore the flow at any point from a unique, cached flowExecutionId in local history.)
So of the three flow execution storage strategies, the default "session" requires some storage, but not as much as the "continuations-based session" strategy. In those cases, the ExpiredFlowCleanupFilter can help for abandonded/errored out flows, as normal flows that reach a end state will always be cleaned up automatically. The client strategy requires no session state at all, but has some other tradeoffs (e.g security issues, limitations with GET
Core Spring Development Team