{"record":{"id":"cbc5488d116da201","repo":"mastra-ai/mastra","slug":"mastracompositestore-requires-at-least-one-storage","errorCode":null,"errorMessage":"MastraCompositeStore requires at least one storage source. Provide a default storage, an editor storage, or domain overrides.","messagePattern":"MastraCompositeStore requires at least one storage source\\. Provide a default storage, an editor storage, or domain overrides\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/storage/base.ts","lineNumber":405,"sourceCode":"    // If composition config is provided (default, editor, or domains), compose the stores\n    if (config.default || config.editor || config.domains) {\n      const defaultStores = config.default?.stores;\n      const editorStores = config.editor?.stores;\n      const domainOverrides = config.domains ?? {};\n\n      // Retain the parent store refs so init() can delegate to their own\n      // init() — see field doc above and init() below.\n      this.parentDefault = config.default;\n      this.parentEditor = config.editor;\n\n      // Validate that at least one storage source is provided (a `false`\n      // override disables a domain, so it doesn't count as a source)\n      const hasDefaultDomains = defaultStores && Object.values(defaultStores).some(v => v !== undefined);\n      const hasEditorDomains = editorStores && Object.values(editorStores).some(v => v !== undefined);\n      const hasOverrideDomains = Object.values(domainOverrides).some(v => v !== undefined && v !== false);\n\n      if (!hasDefaultDomains && !hasEditorDomains && !hasOverrideDomains) {\n        throw new Error(\n          'MastraCompositeStore requires at least one storage source. Provide a default storage, an editor storage, or domain overrides.',\n        );\n      }\n\n      const editorDomainSet = new Set<string>(EDITOR_DOMAINS);\n\n      // Helper: resolve a domain with priority: domains > editor (for editor domains) > default.\n      // A `false` override disables the domain — it resolves to undefined\n      // instead of falling through to the editor/default stores.\n      const resolve = <K extends keyof StorageDomains>(key: K): StorageDomains[K] | undefined => {\n        const override: StorageDomains[K] | false | undefined = domainOverrides[key];\n        if (override === false) return undefined;\n        if (override !== undefined) return override;\n        if (editorDomainSet.has(key) && editorStores?.[key] !== undefined) return editorStores[key];\n        return defaultStores?.[key];\n      };\n\n      // Build the composed stores object by iterating the typed key list so","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/storage/base.ts#L387-L423","documentation":"A MastraCompositeStore must resolve at least one actual storage source: a default storage, an editor storage, or at least one domain override that is defined and not `false`. If every domain value is undefined or the maps are empty, the composite store would have nothing to delegate to, so the constructor throws.","triggerScenarios":"Constructing MastraCompositeStore with all of `defaultStores`, `editorStores`, and `domainOverrides` empty or with every value set to `undefined`/`false` — e.g. `{ defaultStores: { agents: undefined } }` or an entirely empty config.","commonSituations":"Conditional config building where all optional stores were omitted; disabling every domain via `false` overrides; passing a variable that is undefined instead of a store instance due to a failed import or init.","solutions":["Pass at least one concrete store, e.g. `defaultStores: { agents: myAgentStorage }`","Verify the store variables are actually initialized/defined before being spread into the config","If intentionally disabling domains, keep at least one domain backed by a real store"],"exampleFix":"// before\nnew MastraCompositeStore({ id: 's', defaultStores: { agents: undefined } });\n// after\nnew MastraCompositeStore({ id: 's', defaultStores: { agents: new MastraStorage({ name: 'main', ... }) } });","handlingStrategy":"validation","validationCode":"const domains = { ...defaultStores, ...editorStores, ...domainOverrides };\nconst hasSource = Object.values(domains).some(v => v !== undefined && v !== false);\nif (!hasSource) throw new Error('Composite store config has no storage sources');","typeGuard":"function hasStorageSource(config: MastraCompositeStoreConfig): boolean {\n  return (\n    Object.values(config.defaultStores ?? {}).some(v => v !== undefined) ||\n    Object.values(config.editorStores ?? {}).some(v => v !== undefined) ||\n    Object.values(config.domainOverrides ?? {}).some(v => v !== undefined && v !== false)\n  );\n}","tryCatchPattern":"try {\n  store = new MastraCompositeStore(config);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('requires at least one storage source')) {\n    throw new Error(`Composite store '${config.id}' configured with no storage sources — check your store initialization order`);\n  }\n  throw e;\n}","preventionTips":["Always provide at least one concrete store (e.g. a default storage) in the config","Check that store variables are initialized (imports/async init resolved) before constructing","Avoid disabling every domain with `false` overrides","Validate config objects at startup, before anything depends on the store"],"tags":["storage","configuration","composite-store"],"backgroundTag":"missing-required-config-field","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}