beekeeper-studio/beekeeper-studio · warning
Query not ready to be canceled
Error message
Query not ready to be canceled
What it means
In SqliteClient's query execution, a dedicated worker 'queryConnection' is opened asynchronously while the cancel() closure is returned immediately. cancel() throws 'Query not ready to be canceled' if the closure-scoped queryConnection variable is still null — i.e. cancellation was requested before the worker connection finished opening (or it was never assigned). It signals the query cannot be canceled at that moment, not that the query itself failed.
Source
Thrown at apps/studio/src/lib/db/clients/sqlite.ts:315
if (err.code === sqliteErrors.CANCELED) {
err.sqlectronError = 'CANCELED_BY_USER';
}
if (err.message?.startsWith('no such column')) {
const nuError = new ClientError(`${err.message} - Check that you only use double quotes (") for identifiers, not strings`, "https://docs.beekeeperstudio.io/support/troubleshooting/#no-such-column-x");
throw nuError
}
throw err;
} finally {
if (queryConnection !== this._rawConnection) {
queryConnection.close();
}
}
}).bind(this),
async cancel() {
if (!queryConnection) {
throw new Error('Query not ready to be canceled');
}
}
}
}
async executeQuery(queryText: string, options: any = {}): Promise<NgQueryResult[]> {
const arrayMode: boolean = options.arrayMode;
const result = await this.driverExecuteMultiple(queryText, options);
const commands = this.identifyCommands(queryText)
return (result || []).map(({ rows: data, columns, statement, changes }, i) => {
// Fallback in case the identifier could not reconize the command
const text = commands[i]?.text;
const isSelect = Array.isArray(data);
let rows: any[];
let fields: any[];
if (isSelect && arrayMode) {View on GitHub (pinned to 4e3e03e322)
Solutions
- Delay cancellation slightly and retry until queryConnection is assigned (poll or wait a tick).
- Treat this error as benign: check whether the query already completed before showing a failure.
- Serialize cancellation: disable the cancel button until the query reports it is actually running.
- Track the query's lifecycle and make cancel() a no-op when the query is already finished or the connection closed.
Example fix
// before
await handle.cancel();
// after
try {
await handle.cancel();
} catch (err) {
if (!/not ready to be canceled/i.test(err.message)) throw err; // query likely already done
} Defensive patterns
Strategy: retry
Validate before calling
// only cancel once the query reports it is running if (!queryHandle.isRunning || !queryHandle.isRunning()) return;
Type guard
function isCancelable(handle: QueryHandle): boolean {
return typeof handle.cancel === 'function' && handle.isRunning?.() === true;
} Try / catch
const cancelWithRetry = async (handle, retries = 3) => {
for (let i = 0; i < retries; i++) {
try { return await handle.cancel(); }
catch (err) {
if (!/not ready to be canceled/i.test(err.message) || i === retries - 1) {
if (/not ready to be canceled/i.test(err.message)) return; // query likely done
throw err;
}
await new Promise(r => setTimeout(r, 100));
}
}
}; Prevention
- Delay enabling the cancel button until the query reports running
- Treat 'not ready to be canceled' as benign (query setup or already finished)
- Debounce duplicate cancel clicks
- Remember SQLite queries run on a worker connection opened asynchronously
When it happens
Trigger: Calling cancel() on the query handle immediately after starting a query, before the SQLite worker connection has opened; canceling after the connection already closed; racing a cancel against a very fast query that finished and tore down the connection.
Common situations: UIs with a cancel button that can be clicked during the brief connection-setup window; automated tests canceling instantly; user cancels a long query twice and the second cancel lands after teardown.
Related errors
- Query not ready to be canceled
- Query not ready to be canceled
- Query not ready to be canceled
- You need to call start first
- No statement to cancel
AI-assisted analysis of beekeeper-studio/beekeeper-studio@4e3e03e322 (2026-08-31).
Data as JSON: /api/errors/0b6b4907050c68a2.
Report an issue: GitHub.