mastra-ai/mastra · error · Error

MastraCompositeStore requires at least one storage source. P

Error message

MastraCompositeStore requires at least one storage source. Provide a default storage, an editor storage, or domain overrides.

What it means

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.

Source

Thrown at packages/core/src/storage/base.ts:405

    // If composition config is provided (default, editor, or domains), compose the stores
    if (config.default || config.editor || config.domains) {
      const defaultStores = config.default?.stores;
      const editorStores = config.editor?.stores;
      const domainOverrides = config.domains ?? {};

      // Retain the parent store refs so init() can delegate to their own
      // init() — see field doc above and init() below.
      this.parentDefault = config.default;
      this.parentEditor = config.editor;

      // Validate that at least one storage source is provided (a `false`
      // override disables a domain, so it doesn't count as a source)
      const hasDefaultDomains = defaultStores && Object.values(defaultStores).some(v => v !== undefined);
      const hasEditorDomains = editorStores && Object.values(editorStores).some(v => v !== undefined);
      const hasOverrideDomains = Object.values(domainOverrides).some(v => v !== undefined && v !== false);

      if (!hasDefaultDomains && !hasEditorDomains && !hasOverrideDomains) {
        throw new Error(
          'MastraCompositeStore requires at least one storage source. Provide a default storage, an editor storage, or domain overrides.',
        );
      }

      const editorDomainSet = new Set<string>(EDITOR_DOMAINS);

      // Helper: resolve a domain with priority: domains > editor (for editor domains) > default.
      // A `false` override disables the domain — it resolves to undefined
      // instead of falling through to the editor/default stores.
      const resolve = <K extends keyof StorageDomains>(key: K): StorageDomains[K] | undefined => {
        const override: StorageDomains[K] | false | undefined = domainOverrides[key];
        if (override === false) return undefined;
        if (override !== undefined) return override;
        if (editorDomainSet.has(key) && editorStores?.[key] !== undefined) return editorStores[key];
        return defaultStores?.[key];
      };

      // Build the composed stores object by iterating the typed key list so

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass at least one concrete store, e.g. `defaultStores: { agents: myAgentStorage }`
  2. Verify the store variables are actually initialized/defined before being spread into the config
  3. If intentionally disabling domains, keep at least one domain backed by a real store

Example fix

// before
new MastraCompositeStore({ id: 's', defaultStores: { agents: undefined } });
// after
new MastraCompositeStore({ id: 's', defaultStores: { agents: new MastraStorage({ name: 'main', ... }) } });
Defensive patterns

Strategy: validation

Validate before calling

const domains = { ...defaultStores, ...editorStores, ...domainOverrides };
const hasSource = Object.values(domains).some(v => v !== undefined && v !== false);
if (!hasSource) throw new Error('Composite store config has no storage sources');

Type guard

function hasStorageSource(config: MastraCompositeStoreConfig): boolean {
  return (
    Object.values(config.defaultStores ?? {}).some(v => v !== undefined) ||
    Object.values(config.editorStores ?? {}).some(v => v !== undefined) ||
    Object.values(config.domainOverrides ?? {}).some(v => v !== undefined && v !== false)
  );
}

Try / catch

try {
  store = new MastraCompositeStore(config);
} catch (e) {
  if (e instanceof Error && e.message.includes('requires at least one storage source')) {
    throw new Error(`Composite store '${config.id}' configured with no storage sources — check your store initialization order`);
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/cbc5488d116da201. Report an issue: GitHub.