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 soView on GitHub (pinned to 75dd419e61)
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
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
- 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
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
- AcpAgent does not support resuming suspended generate calls
- ACP prompt stopped before completing: ${response.stopReason}
- MastraAuthBetterAuth needs a database to build its own bette
- [Slack] Failed to resolve Mastra storage. Ensure your Mastra
- [Slack] No storage available. SlackProvider requires persist
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/cbc5488d116da201.
Report an issue: GitHub.