             _queryHandler = null;
             // Note that we still may need to throw away any number of DataRow messages
             _hasCodecError = true; 
+        }
+
+        private function ensureConnected():void {
+            if (!_connected) {
+                _connHandler.handleStreamError(new Error("Not connected"));
+            }
+        }
+
+        private function ensureReady():void {
+            if (!_rfq) {
+                onProtocolError(new ProtocolError("FEBEConnection is not ready for query"));
+            }
         }
 
     }

        // query-data-available and statement-complete messages. We should also batch
        // the data-available messages--dispatching an event per-DataRow would be silly.
        public function executeSimpleQuery(sql:String, handler:IQueryHandler):void {
            if (!_rfq) {
                throw new ArgumentError("FEBEConnection is not ready for query");
            }
            _rfq = false;
            _queryHandler = handler;
            send(new Query(sql));
        }

        public function executeQuery(sql:String, params:Array, handler:IQueryHandler):void {
            // > parse(statement)
            // < parseComplete | errorResponse
            // > bind(portal)

        // support a structured explain

        public function cancel():void {
            ensureConnected();
            // Note that cancel needs to happen in a separate connection to make any sense.
            // Since the broker goes out of scope here as soon as the method body ends,
            // there may be some issues with GC (since socket communication is asynchronous),
            // but Flash Player *should* queue everything it needs to do the physical send
            // before GC. To do this right, we'd probably have to keep a reference to this
            // broker and listen for close (or error) and only remove the reference then
            try {
                var cancelBroker:IMessageBroker = _brokerFactory.create();
                cancelBroker.send(new CancelRequest(_backendPid, _backendKey));
                try {
                    cancelBroker.close();
                } catch (e:Error) {
                    LOGGER.warn("Could not close cancel broker: " + e.message);
                }
            } catch (e:Error) {
                LOGGER.warn("Could not cancel statement: " + e.message);
            }
        }

        private function handleStreamError(e:MessageStreamErrorEvent):void {
