{"record":{"id":"8d1016cf04083737","repo":"cube-js/cube","slug":"createoptions-driverfactory-function-must-return-e","errorCode":null,"errorMessage":"CreateOptions.driverFactory function must return either BaseDriver or DriverConfig.","messagePattern":"CreateOptions\\.driverFactory function must return either BaseDriver or DriverConfig\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cubejs-server-core/src/core/OptsHandler.ts","lineNumber":101,"sourceCode":"      throw new Error(\n        'Either CUBEJS_DB_TYPE or CreateOptions.driverFactory must be specified'\n      );\n    }\n\n    return validated;\n  }\n\n  /**\n   * Assert value returned from the driver factory.\n   */\n  private assertDriverFactoryResult(\n    val: DriverConfig | BaseDriver,\n  ) {\n    if (isDriver(val)) {\n      if (!this.driverFactoryType) {\n        this.driverFactoryType = 'BaseDriver';\n      } else if (this.driverFactoryType !== 'BaseDriver') {\n        throw new Error(\n          'CreateOptions.driverFactory function must return either ' +\n          'BaseDriver or DriverConfig.'\n        );\n      }\n      return <BaseDriver>val;\n    } else if (\n      val && (<DriverConfig>val).type && typeof (<DriverConfig>val).type === 'string'\n    ) {\n      if (!this.driverFactoryType) {\n        this.driverFactoryType = 'DriverConfig';\n      } else if (this.driverFactoryType !== 'DriverConfig') {\n        throw new Error(\n          'CreateOptions.driverFactory function must return either ' +\n          'BaseDriver or DriverConfig.'\n        );\n      }\n      return <DriverConfig>val;\n    } else {","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/packages/cubejs-server-core/src/core/OptsHandler.ts#L83-L119","documentation":"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.","triggerScenarios":"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' }.","commonSituations":"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.","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"],"exampleFix":"// before\ndriverFactory: async (ctx) => ctx.dataSource === 'a' ? new PostgresDriver(opts) : { type: 'mysql' }\n// after\ndriverFactory: async (ctx) => ctx.dataSource === 'a' ? { type: 'postgres', ...opts } : { type: 'mysql' }","handlingStrategy":"type-guard","validationCode":"import { isDriver } from '@cubejs-backend/shared'; // or a duck-type check\nfunction assertConsistentFactoryShape(factory, ctxs) {\n  const shapes = ctxs.map(c => typeof factory(c) === 'object' && 'type' in factory(c) ? 'DriverConfig' : 'BaseDriver');\n  if (new Set(shapes).size > 1) throw new Error('driverFactory must consistently return one shape');\n}","typeGuard":"function isDriverConfig(val) {\n  return val != null && typeof val === 'object' && !('testConnection' in val) && typeof val.type === 'string';\n}","tryCatchPattern":"try {\n  await driverFactory(ctx);\n} catch (e) {\n  if (e.message.includes('must return either BaseDriver or DriverConfig')) {\n    console.error('driverFactory returned mixed shapes across calls; unify to DriverConfig.');\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["driver-factory","config","consistency","multi-data-source"],"backgroundTag":"inconsistent-driver-factory-return","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}