cube-js/cube · critical
Connection check failed: ${errorMessage}
Error message
Connection check failed: ${errorMessage} What it means
ClickHouseDriver.withCancel pings the ClickHouse server through @clickhouse/client before executing the wrapped query/callback. If the ping fails, the driver wraps the ping error (stringified, with special handling for AggregateError when the hostname resolves to multiple addresses) and throws 'Connection check failed: <error>'. It aborts before running user SQL so queries don't hit a dead connection.
Source
Thrown at packages/cubejs-clickhouse-driver/src/ClickHouseDriver.ts:222
this.client = this.createClient(maxPoolSize);
}
protected withCancel<T>(fn: (con: ClickHouseClient, queryId: string, signal: AbortSignal) => Promise<T>): Promise<T> {
const queryId = uuidv4();
const abortController = new AbortController();
const { signal } = abortController;
const promise = (async () => {
const pingResult = await this.client.ping();
if (!pingResult.success) {
// TODO replace string formatting with proper cause
// pingResult.error can be AggregateError when ClickHouse hostname resolves to multiple addresses
let errorMessage = pingResult.error.toString();
if (pingResult.error instanceof AggregateError) {
errorMessage = `Aggregate error: ${pingResult.error.message}; errors: ${pingResult.error.errors.join('; ')}`;
}
throw new Error(`Connection check failed: ${errorMessage}`);
}
signal.throwIfAborted();
// Queries sent by `fn` can hit a timeout error, would _not_ get killed, and continue running in ClickHouse
// TODO should we kill those as well?
const result = await fn(this.client, queryId, signal);
signal.throwIfAborted();
return result;
})();
(promise as any).cancel = async () => {
abortController.abort();
// Use separate client for kill query, usual pool may be busy
const killClient = this.createClient(1);
try {
await killClient.command({
query: `KILL QUERY WHERE query_id = '${queryId}'`,
});
} finally {
await killClient.close();View on GitHub (pinned to 7d981676b3)
Solutions
- Check the wrapped message: for AggregateError, look at the per-address errors to see which IP/cause failed
- Verify ClickHouse is reachable: curl http://<host>:8123/ping from the Cube process host
- Correct driver config (host, port, protocol http/https, username/password) in the constructor options
- Fix DNS/load-balancer so the resolved address is reachable, or pin a single resolvable address
Example fix
// before
const driver = new ClickHouseDriver({ host: 'http://clickhouse:8443' }); // wrong port/protocol
// after
const driver = new ClickHouseDriver({ host: 'https://clickhouse:8443' }); Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight reachability check
const res = await fetch(`${host}/ping`).catch(() => null);
if (!res || !res.ok) {
throw new Error(`ClickHouse unreachable at ${host}; check server/port/protocol`);
} Try / catch
try {
await cube.query(query);
} catch (e) {
if (e.message.startsWith('Connection check failed:')) {
if (e.message.includes('Aggregate error')) {
// multi-address DNS issue: inspect per-address errors
}
// retry with backoff or fail fast on startup
}
} Prevention
- Add a startup health check against /ping before serving traffic
- Use a single stable hostname/IP for the ClickHouse endpoint
- Match protocol (http vs https) to the actual server port
When it happens
Trigger: query(), command(), or insert() calls when the initial ping to the ClickHouse host fails: server down, wrong host/port, TLS mismatch, DNS failure, or unreachable network from the container.
Common situations: ClickHouse container not started in docker-compose; wrong ClickHouseDriver host/port/protocol options; AggregateError when the hostname resolves to multiple IPs (e.g. headless service in k8s) with some unreachable; firewall blocking the native HTTP port 8123.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- Unexpected stream end before row with names
- Unexpected stream end before row with types
- Stream query failed: ${e}; query id: ${queryId}
- Unable to connect to the database (${poolName}): ${message}
- HTTP error! status: ${response.status}
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/efb6ed08515e9485.
Report an issue: GitHub.