{"record":{"id":"0c2bf514852e68f7","repo":"cube-js/cube","slug":"unable-to-detect-column-types-for-pre-aggregation","errorCode":null,"errorMessage":"Unable to detect column types for pre-aggregation on empty values in readOnly mode.","messagePattern":"Unable to detect column types for pre-aggregation on empty values in readOnly mode\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cubejs-base-driver/src/type-detection.ts","lineNumber":60,"sourceCode":"\n    const normalized = v.toString().toLowerCase();\n\n    return normalized === 'true' || normalized === 'false';\n  },\n  string: (v) => v.length < 256,\n  text: () => true\n};\n\nconst MATCHER_TYPES = Object.keys(DbTypeValueMatcher);\n\n// While detecting column types the first row is normally enough, but when it\n// holds NULLs we keep scanning further rows until every column has a concrete\n// value to infer its type from. This bounds how many rows we inspect in that case.\nconst DB_TYPE_DETECTION_MAX_ROWS = 100;\n\nexport function detectTypesFromTabular(rows: Row[]): TableStructure {\n  if (rows.length === 0) {\n    throw new Error(\n      'Unable to detect column types for pre-aggregation on empty values in readOnly mode.'\n    );\n  }\n\n  const fields = Object.keys(rows[0]);\n\n  // Non-null values sampled per column while scanning rows.\n  const valuesByField: Record<string, any[]> = {};\n\n  for (const field of fields) {\n    valuesByField[field] = [];\n  }\n\n  const unresolvedFields = new Set(fields);\n  const rowsToScan = Math.min(rows.length, DB_TYPE_DETECTION_MAX_ROWS);\n\n  for (let i = 0; i < rowsToScan; i++) {\n    const row = rows[i];","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-base-driver/src/type-detection.ts#L42-L78","documentation":"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).","triggerScenarios":"Calling types()/detectTypesFromTabular() with an empty rows array — e.g. a pre-aggregation query over an empty table or a filter matching no rows.","commonSituations":"Pre-aggregation build against an empty source table, an overly restrictive filter eliminating all rows, or a partition with no data.","solutions":["Ensure the source table/partition has data before building the pre-aggregation","Relax or fix query filters that eliminate all rows","Provide explicit column types in the schema so runtime type detection is not needed","If detection is possible, allow the driver to use database metadata (non-readOnly path)"],"exampleFix":"// before\nconst structure = detectTypesFromTabular([]); // throws\n// after\nif (rows.length === 0) {\n  structure = columns.map(c => ({ name: c.name, type: 'text' })); // explicit defaults\n} else {\n  structure = detectTypesFromTabular(rows);\n}","handlingStrategy":"validation","validationCode":"if (rows.length === 0) {\n  throw new Error('Source query returned no rows; supply explicit column types or fix filters before building the pre-agg');\n}\nconst structure = detectTypesFromTabular(rows);","typeGuard":"function hasRows(rows: Row[]): rows is [Row, ...Row[]] {\n  return rows.length > 0;\n}","tryCatchPattern":"try {\n  structure = detectTypesFromTabular(rows);\n} catch (e) {\n  if (/Unable to detect column types/.test(e.message)) {\n    structure = explicitSchemaTypes();\n  } else throw e;\n}","preventionTips":["Define explicit column types in the data model to avoid runtime detection","Guard against empty tables/partitions before pre-agg builds","Check filters for over-restriction that removes all rows","Seed or validate data presence in CI before build jobs"],"tags":["type-detection","pre-aggregation","empty-result"],"backgroundTag":"cannot-detect-column-types","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}