cube-js/cube · error · UserError

Approximate distinct count is not supported by this DB

Error message

Approximate distinct count is not supported by this DB

What it means

countDistinctApprox() is the dialect hook that generates the approximate distinct count SQL (e.g. APPROX_COUNT_DISTINCT, HLL_COUNT.INIT). BaseQuery's default implementation throws this UserError, meaning the DB dialect never opted into approximate counting.

Source

Thrown at packages/cubejs-schema-compiler/src/adapter/BaseQuery.js:4014

  hllCardinality(_sql) {
    throw new UserError('Distributed approximate distinct count is not supported by this DB');
  }

  hllMergeOnly(sql) {
    return this.hllMerge(sql);
  }

  hllCardinalityMerge(sql) {
    return this.hllMerge(sql);
  }

  castToString(sql) {
    return `CAST(${sql} as TEXT)`;
  }

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  countDistinctApprox(sql) {
    throw new UserError('Approximate distinct count is not supported by this DB');
  }

  primaryKeyCount(cubeName, distinct) {
    const primaryKeys = this.cubeEvaluator.primaryKeys[cubeName];
    const primaryKeySql = primaryKeys.length > 1 ?
      this.concatStringsSql(primaryKeys.map((pk) => this.castToString(this.primaryKeySql(pk, cubeName)))) :
      this.primaryKeySql(primaryKeys[0], cubeName);
    return `count(${distinct ? 'distinct ' : ''}${primaryKeySql})`;
  }

  renderDimensionCase(symbol, cubeName) {
    const when = symbol.case.when.map(w => ({
      sql: this.evaluateSql(cubeName, w.sql),
      label: this.renderDimensionCaseLabel(w.label, cubeName)
    }));
    return this.caseWhenStatement(
      when,
      symbol.case.else && this.renderDimensionCaseLabel(symbol.case.else.label, cubeName)

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Change the measure type from countDistinctApprox to countDistinct
  2. Use a data source adapter supporting approximate counts
  3. Extend your adapter and implement countDistinctApprox using a native approximation function or a UDF

Example fix

// before
measures:
  - name: unique_users
    type: countDistinctApprox
    sql: user_id
// after
measures:
  - name: unique_users
    type: countDistinct
    sql: user_id
Defensive patterns

Strategy: fallback

Validate before calling

const approxSupporting = ['postgres','bigquery','clickhouse','snowflake','duckdb','databricks-jdbc'];
if (!approxSupporting.includes(dataSource)) {
  throw new Error(`countDistinctApprox unsupported on ${dataSource}; use countDistinct`);
}

Type guard

function supportsApproxCount(adapter) {
  return typeof adapter.countDistinctApprox === 'function' &&
    adapter.countDistinctApprox !== BaseQuery.prototype.countDistinctApprox;
}

Try / catch

try { return await cube.load(query); } catch (e) {
  if (/Approximate distinct count is not supported/.test(e.message)) {
    return await cube.load(swapApproxForExact(query));
  }
  throw e;
}

Prevention

When it happens

Trigger: Querying a measure with type countDistinctApprox (or SQL_API features requiring it) against an adapter that does not override countDistinctApprox.

Common situations: Copy-pasting a schema with countDistinctApprox measures from a BigQuery/ClickHouse project to a DB like MySQL or plain Postgres without the HLL extension.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/d681efe59253f0f2. Report an issue: GitHub.