cube-js/cube · error · Error

Unable to detect column types for pre-aggregation on empty v

Error message

Unable to detect column types for pre-aggregation on empty values in readOnly mode.

What it means

detectTypesFromTabular() infers column types from result rows. In readOnly mode there is no other way to detect types, and if the rows array is empty it cannot infer anything, so it throws this explicit error (scanning is bounded by DB_TYPE_DETECTION_MAX_ROWS).

Source

Thrown at packages/cubejs-base-driver/src/type-detection.ts:60

    const normalized = v.toString().toLowerCase();

    return normalized === 'true' || normalized === 'false';
  },
  string: (v) => v.length < 256,
  text: () => true
};

const MATCHER_TYPES = Object.keys(DbTypeValueMatcher);

// While detecting column types the first row is normally enough, but when it
// holds NULLs we keep scanning further rows until every column has a concrete
// value to infer its type from. This bounds how many rows we inspect in that case.
const DB_TYPE_DETECTION_MAX_ROWS = 100;

export function detectTypesFromTabular(rows: Row[]): TableStructure {
  if (rows.length === 0) {
    throw new Error(
      'Unable to detect column types for pre-aggregation on empty values in readOnly mode.'
    );
  }

  const fields = Object.keys(rows[0]);

  // Non-null values sampled per column while scanning rows.
  const valuesByField: Record<string, any[]> = {};

  for (const field of fields) {
    valuesByField[field] = [];
  }

  const unresolvedFields = new Set(fields);
  const rowsToScan = Math.min(rows.length, DB_TYPE_DETECTION_MAX_ROWS);

  for (let i = 0; i < rowsToScan; i++) {
    const row = rows[i];

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Ensure the source table/partition has data before building the pre-aggregation
  2. Relax or fix query filters that eliminate all rows
  3. Provide explicit column types in the schema so runtime type detection is not needed
  4. If detection is possible, allow the driver to use database metadata (non-readOnly path)

Example fix

// before
const structure = detectTypesFromTabular([]); // throws
// after
if (rows.length === 0) {
  structure = columns.map(c => ({ name: c.name, type: 'text' })); // explicit defaults
} else {
  structure = detectTypesFromTabular(rows);
}
Defensive patterns

Strategy: validation

Validate before calling

if (rows.length === 0) {
  throw new Error('Source query returned no rows; supply explicit column types or fix filters before building the pre-agg');
}
const structure = detectTypesFromTabular(rows);

Type guard

function hasRows(rows: Row[]): rows is [Row, ...Row[]] {
  return rows.length > 0;
}

Try / catch

try {
  structure = detectTypesFromTabular(rows);
} catch (e) {
  if (/Unable to detect column types/.test(e.message)) {
    structure = explicitSchemaTypes();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling types()/detectTypesFromTabular() with an empty rows array — e.g. a pre-aggregation query over an empty table or a filter matching no rows.

Common situations: Pre-aggregation build against an empty source table, an overly restrictive filter eliminating all rows, or a partition with no data.

Related errors


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