{"record":{"id":"8d344aff65d08bd1","repo":"mastra-ai/mastra","slug":"storagebackend-is-required-when-injecting-a-custom","errorCode":null,"errorMessage":"storageBackend is required when injecting a custom storage instance.","messagePattern":"storageBackend is required when injecting a custom storage instance\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/index.ts","lineNumber":401,"sourceCode":"  return typeof candidate.init === 'function' && typeof candidate.__registerMastra === 'function';\n}\n\n/** Cross-copy-safe class check: walks the prototype chain by constructor name. */\nfunction hasAncestorClassNamed(value: object, className: string): boolean {\n  for (let proto = Object.getPrototypeOf(value); proto; proto = Object.getPrototypeOf(proto)) {\n    if (proto.constructor?.name === className) return true;\n  }\n  return false;\n}\n\nfunction resolveInjectedStorageBackend(\n  storage: MastraCompositeStore,\n  configuredBackend?: 'libsql' | 'pg',\n): 'libsql' | 'pg' {\n  if (configuredBackend) return configuredBackend;\n  if (storage instanceof LibSQLStore || hasAncestorClassNamed(storage, 'LibSQLStore')) return 'libsql';\n  if (storage instanceof PostgresStore || hasAncestorClassNamed(storage, 'PostgresStore')) return 'pg';\n  throw new Error('storageBackend is required when injecting a custom storage instance.');\n}\n\nexport async function createMastraCodeAgentController(config?: MastraCodeConfig) {\n  const cwd = config?.cwd ?? process.cwd();\n  const homeDir = config?.homeDir ?? config?.initialState?.homeDir;\n  const configDir = config?.configDir ?? DEFAULT_CONFIG_DIR;\n  // The single session for this process, assigned once `createSession()` runs\n  // below. Config callbacks defined before then (e.g. notification stream\n  // options) read it lazily through this holder.\n  let activeSession: Session<MastraCodeState> | undefined;\n  // Same trick for the controller, which plugins reach through a lazy accessor.\n  // Plugins load well before the controller is constructed, and a closure over\n  // the `controller` binding itself would throw on early access rather than\n  // reporting \"not ready yet\", so the accessor reads this holder instead.\n  let pluginRuntimeController: AgentController<MastraCodeState> | undefined;\n  if (configDir !== DEFAULT_CONFIG_DIR) {\n    validateConfigDirName(configDir);\n  }","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/index.ts#L383-L419","documentation":"resolveInjectedStorageBackend() maps an injected MastraCompositeStore to a concrete backend name ('libsql' or 'pg'). It trusts an explicit configuredBackend; otherwise it detects LibSQLStore or PostgresStore by instanceof or ancestor class name. Any other custom storage class is unsupported, so callers must declare the backend themselves via the storageBackend option.","triggerScenarios":"Passing a custom storage instance (not LibSQLStore/PostgresStore, and not a subclass of either) to createMastraCodeAgentController({ storage }) without also passing storageBackend: 'libsql' | 'pg' — and with no configuredBackend, detection falls through to the throw.","commonSituations":"Wrapping stores in a custom class or proxy (breaks instanceof and ancestor-name detection); using a community/third-party Mastra store; minification or renaming that defeats hasAncestorClassNamed.","solutions":["Pass the backend explicitly: createMastraCodeAgentController({ storage: myStore, storageBackend: 'pg' }) (or 'libsql').","Extend LibSQLStore or PostgresStore so the built-in detection recognizes your instance.","If wrapping a store, keep the underlying store's class in the prototype chain so ancestor detection still matches."],"exampleFix":"// before\ncreateMastraCodeAgentController({ storage: new MyCustomStore() });\n// after\ncreateMastraCodeAgentController({ storage: new MyCustomStore(), storageBackend: 'pg' });","handlingStrategy":"validation","validationCode":"const isLibsql = storage instanceof LibSQLStore;\nconst isPg = storage instanceof PostgresStore;\nif (!isLibsql && !isPg && !storageBackend) {\n  throw new Error(\"storageBackend ('libsql' | 'pg') is required for custom storage instances\");\n}","typeGuard":"function hasDeclaredBackend(\n  s: unknown,\n): s is { storage: MastraCompositeStore; storageBackend: 'libsql' | 'pg' } {\n  const o = s as { storage?: unknown; storageBackend?: unknown };\n  return o.storage != null && (o.storageBackend === 'libsql' || o.storageBackend === 'pg');\n}","tryCatchPattern":"try {\n  controller = await createMastraCodeAgentController({ storage: myStore });\n} catch (err) {\n  if (err instanceof Error && err.message.includes('storageBackend is required')) {\n    controller = await createMastraCodeAgentController({ storage: myStore, storageBackend: 'pg' });\n  } else { throw err; }\n}","preventionTips":["Always pair a custom storage instance with an explicit storageBackend option.","Prefer subclassing LibSQLStore/PostgresStore so built-in detection works.","Avoid proxies/decorators that hide the store's prototype chain."],"tags":["storage","configuration","dependency-injection"],"backgroundTag":"missing-storage-backend","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}