cube-js/cube · error · Error
CreateOptions.driverFactory function must return either Base
Error message
CreateOptions.driverFactory function must return either BaseDriver or DriverConfig.
What it means
assertDriverFactoryResult remembers whether your driverFactory has returned a BaseDriver instance or a plain DriverConfig ({ type, ... }) object. If the factory already returned a DriverConfig and later returns a BaseDriver instance (or vice versa), it throws, because mixing return shapes across calls (per data source / per pre-aggregation context) is unsupported. The check enforces a consistent factory contract.
Source
Thrown at packages/cubejs-server-core/src/core/OptsHandler.ts:101
throw new Error(
'Either CUBEJS_DB_TYPE or CreateOptions.driverFactory must be specified'
);
}
return validated;
}
/**
* Assert value returned from the driver factory.
*/
private assertDriverFactoryResult(
val: DriverConfig | BaseDriver,
) {
if (isDriver(val)) {
if (!this.driverFactoryType) {
this.driverFactoryType = 'BaseDriver';
} else if (this.driverFactoryType !== 'BaseDriver') {
throw new Error(
'CreateOptions.driverFactory function must return either ' +
'BaseDriver or DriverConfig.'
);
}
return <BaseDriver>val;
} else if (
val && (<DriverConfig>val).type && typeof (<DriverConfig>val).type === 'string'
) {
if (!this.driverFactoryType) {
this.driverFactoryType = 'DriverConfig';
} else if (this.driverFactoryType !== 'DriverConfig') {
throw new Error(
'CreateOptions.driverFactory function must return either ' +
'BaseDriver or DriverConfig.'
);
}
return <DriverConfig>val;
} else {View on GitHub (pinned to 7d981676b3)
Solutions
- Make the driverFactory always return the same shape — prefer DriverConfig objects ({ type, ... }) everywhere
- Or always return driver instances everywhere, but never mix
- Centralize per-data-source config as data (objects) rather than instantiated drivers
- Test all data sources / contexts so every code path of the factory is exercised
Example fix
// before
driverFactory: async (ctx) => ctx.dataSource === 'a' ? new PostgresDriver(opts) : { type: 'mysql' }
// after
driverFactory: async (ctx) => ctx.dataSource === 'a' ? { type: 'postgres', ...opts } : { type: 'mysql' } Defensive patterns
Strategy: type-guard
Validate before calling
import { isDriver } from '@cubejs-backend/shared'; // or a duck-type check
function assertConsistentFactoryShape(factory, ctxs) {
const shapes = ctxs.map(c => typeof factory(c) === 'object' && 'type' in factory(c) ? 'DriverConfig' : 'BaseDriver');
if (new Set(shapes).size > 1) throw new Error('driverFactory must consistently return one shape');
} Type guard
function isDriverConfig(val) {
return val != null && typeof val === 'object' && !('testConnection' in val) && typeof val.type === 'string';
} Try / catch
try {
await driverFactory(ctx);
} catch (e) {
if (e.message.includes('must return either BaseDriver or DriverConfig')) {
console.error('driverFactory returned mixed shapes across calls; unify to DriverConfig.');
}
throw e;
} Prevention
- Have driverFactory return only DriverConfig objects ({ type, ... })
- Never branch the factory to return an instantiated driver for some data sources and a config for others
- Cover every dataSource/context path with tests
- Avoid caching driver instances inside the factory; cache configs instead
When it happens
Trigger: A driverFactory that conditionally returns an instantiated driver for one dataSource and a DriverConfig object for another, e.g. driverFactory: async (ctx) => ctx.dataSource === 'ds1' ? new PostgresDriver({...}) : { type: 'mysql' }.
Common situations: Multi-data-source setups assembled from per-source legacy configs; a factory that falls back to `new SomeDriver()` on error but returns configs normally; refactoring part of a codebase from driver instances to DriverConfig.
Related errors
- Unexpected CreateOptions.driverFactory result value. Must be
- Native api gateway is not enabled
- Timezone must not be empty
- ${type} is required
- Unsupported db type: ${dbType}
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/8d1016cf04083737.
Report an issue: GitHub.