mastra-ai/mastra · error

Dynamic memory factory returned empty value

Error message

Dynamic memory factory returned empty value

What it means

config.memory was provided as a dynamic factory function, but invoking it returned null/undefined (or a falsy value). The controller requires a concrete MastraMemory instance after resolution, so it throws to surface the misbehaving factory.

Source

Thrown at packages/core/src/agent-controller/agent-controller.ts:2286

    return requestContext;
  }

  /**
   * Resolve memory from config — handles both static instances and dynamic factory functions.
   */
  private async resolveMemory(session: Session<TState>): Promise<MastraMemory> {
    const mem = this.config.memory;
    if (!mem) {
      throw new Error('Memory is not configured on this AgentController');
    }
    if (typeof mem !== 'function') {
      return mem;
    }
    const requestContext = await this.buildRequestContext(session);
    const resolved = await Promise.resolve(mem({ requestContext }));
    if (!resolved) {
      throw new Error('Dynamic memory factory returned empty value');
    }
    return resolved;
  }

  // ===========================================================================
  // Token Usage
  // ===========================================================================

  private async persistTokenUsage(session: Session<TState>): Promise<void> {
    const threadId = session.thread.getId();
    if (!threadId || !this.#resolveStorage()) return;

    try {
      const memoryStorage = await this.getMemoryStorage();
      const thread = await memoryStorage.getThreadById({ threadId });
      if (thread) {
        await memoryStorage.saveThread({
          thread: {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Ensure the factory always returns a MastraMemory instance on every code path
  2. Add explicit return statements / assertions inside the factory
  3. Throw inside the factory with a descriptive error when memory cannot be constructed, instead of returning undefined

Example fix

// before
memory: async ({ requestContext }) => {
  if (requestContext.get('tenant')) return buildTenantMemory(requestContext.get('tenant'));
}
// after
memory: async ({ requestContext }) => {
  const tenant = requestContext.get('tenant');
  if (!tenant) throw new Error('No tenant in requestContext; cannot build memory');
  return buildTenantMemory(tenant);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const resolved = await Promise.resolve(config.memory?.({ requestContext }));
if (!resolved) throw new Error('memory factory must return a MastraMemory');

Type guard

function isMemory(v: unknown): v is MastraMemory {
  return !!v && typeof (v as MastraMemory).getThreads === 'function';
}

Try / catch

try {
  return await resolveMemory(session);
} catch (e) {
  if (e instanceof Error && e.message.includes('Dynamic memory factory')) {
    // fall back to a default memory or surface a config error
  }
  throw e;
}

Prevention

When it happens

Trigger: A config.memory async/sync factory that returns undefined — e.g. it conditionally returns nothing when a lookup fails, forgets its return statement, or awaits a function that resolves to void.

Common situations: Factories that branch on requestContext/env and hit an implicit undefined return; returning a promise-wrapped value incorrectly; switching from a static instance to a factory during a refactor.

Related errors


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