cube-js/cube · error
No cancel handler for ${queryHandler}
Error message
No cancel handler for ${queryHandler} What it means
processCancel looks up a cancel handler registered in this.cancelHandlers keyed by the query's queryHandler name; if none was registered for that handler it throws instead of silently ignoring the cancel request. Only handlers explicitly registered via addCancelHandler (or the defaults like 'query') can be cancelled.
Source
Thrown at packages/cubejs-query-orchestrator/src/orchestrator/QueryQueue.ts:1076
queryKey: query.queryKey,
requestId: query.requestId,
error: (e.stack || e).toString(),
queuePrefix: this.redisQueuePrefix
});
} finally {
this.queueDriver.release(queueConnection);
}
}
/**
* Processing cancel query flow.
*/
protected async processCancel(query: QueryDef, queueId: QueueId | null) {
const { queryHandler } = query;
try {
if (!this.cancelHandlers[queryHandler]) {
throw new Error(`No cancel handler for ${queryHandler}`);
}
await this.cancelHandlers[queryHandler](query);
} catch (e: any) {
this.logger('Error while cancel', {
queueId,
queryKey: query.queryKey,
error: e.stack || e,
queuePrefix: this.redisQueuePrefix,
requestId: query.requestId
});
}
}
protected redisHash(queryKey: QueryKey): QueryKeyHash {
return this.queueDriver.redisHash(queryKey);
}
}View on GitHub (pinned to 7d981676b3)
Solutions
- Register a cancel handler for the queryHandler name via queue.addCancelHandler(name, fn)
- Only call cancelQuery for queries using the standard cancellable 'query' handler
- Fix typos in the queryHandler name so it matches a registered handler
Example fix
// before
await queue.cancelQuery(queryWithCustomHandler); // throws: no cancel handler
// after
queue.addCancelHandler('myCustomHandler', async (q) => {
await customRegistry.cancel(q.queryKey);
});
await queue.cancelQuery(queryWithCustomHandler); Defensive patterns
Strategy: validation
Validate before calling
if (!queue.cancelHandlers?.[query.queryHandler]) { console.warn(`Cancel unsupported for handler ${query.queryHandler}`); return false; } Type guard
function isCancelable(q) { return typeof q.queryHandler === 'string' && q.queryHandler in queue.cancelHandlers; } Try / catch
try { await queue.cancelQuery(query); } catch (e) { if (e.message.startsWith('No cancel handler for')) return false; throw e; } Prevention
- Register addCancelHandler for every custom query handler
- Only cancel queries using the standard 'query' handler
- Check the cancelHandlers map before issuing cancellation
When it happens
Trigger: Calling cancelQuery / processCancel for a query whose queryHandler has no entry in cancelHandlers — e.g. custom handlers ('stream', pre-aggregation build handlers, user-registered names) that were never registered with addCancelHandler.
Common situations: Attempting to cancel a pre-aggregation build or streaming query through the standard cancel API; registering a custom query handler but forgetting to register its cancel counterpart; typos in handler names.
Related errors
- Streaming queries to Cube Store aren't supported
- Query was cancelled
- CancelToken was already canceled
- ${this.constructor} driver supports only rows upload
- CubeSQL query was aborted
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/274b2691c9c84e93.
Report an issue: GitHub.