mastra-ai/mastra · error · Error

RunScope: missing required slot ${sym.toString()}

Error message

RunScope: missing required slot ${sym.toString()}

What it means

RunScope stores values under symbol keys; getOrThrow<T>(key) requires the slot to have been set and throws a plain Error naming the missing symbol if it was never populated. It is used to guarantee that messageList, stored, and loopOptions are present before dependent code runs — a slot may be read only after some upstream code called set().

Source

Thrown at packages/core/src/mastra/run-scope.ts:66

  getOrThrow<T>(key: RunScopeKey<T>): T;
  set<T>(key: RunScopeKey<T>, value: T): void;
  delete<T>(key: RunScopeKey<T>): void;
  has<T>(key: RunScopeKey<T>): boolean;
  /** Test-only: number of slots currently populated. */
  readonly size: number;
}

class MapRunScope implements RunScope {
  readonly #slots = new Map<symbol, unknown>();

  get<T>(key: RunScopeKey<T>): T | undefined {
    return this.#slots.get(key as unknown as symbol) as T | undefined;
  }

  getOrThrow<T>(key: RunScopeKey<T>): T {
    const sym = key as unknown as symbol;
    if (!this.#slots.has(sym)) {
      throw new Error(`RunScope: missing required slot ${sym.toString()}`);
    }
    return this.#slots.get(sym) as T;
  }

  set<T>(key: RunScopeKey<T>, value: T): void {
    this.#slots.set(key as unknown as symbol, value);
  }

  delete<T>(key: RunScopeKey<T>): void {
    this.#slots.delete(key as unknown as symbol);
  }

  has<T>(key: RunScopeKey<T>): boolean {
    return this.#slots.has(key as unknown as symbol);
  }

  get size(): number {
    return this.#slots.size;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Use the optional get(key) accessor when the slot may legitimately be absent, and handle undefined.
  2. Ensure the code that sets the slot (scope.set(key, value)) runs before any getOrThrow on that key, in the same request/scope instance.
  3. Pass the same RunScope instance through the call chain instead of constructing a new one.
  4. Wrap getOrThrow in try/catch if absence is expected in some code paths, and fall back to constructing the value.

Example fix

// before
const list = scope.getOrThrow(RunScopeKeys.messageList); // may throw if unset
// after
const list = scope.get(RunScopeKeys.messageList);
if (!list) throw new Error('messageList not yet initialized'); // or initialize it before this point
Defensive patterns

Strategy: fallback

Validate before calling

if (!scope.has?.(RunScopeKeys.messageList)) {
  throw new Error('messageList slot must be set before reading it from RunScope');
}

Try / catch

let messageList;
try {
  messageList = scope.getOrThrow(RunScopeKeys.messageList);
} catch (e) {
  if (e instanceof Error && e.message.startsWith('RunScope: missing required slot')) {
    messageList = createFallbackMessageList(); // or propagate a clearer error
  } else throw e;
}

Prevention

When it happens

Trigger: Calling scope.getOrThrow(RunScopeKeys.messageList) (or stored/loopOptions) on a RunScope where that slot was never set — e.g. reading before the scope was populated, or using a scope instance created independently from the one being filled.

Common situations: Custom agent-loop or storage code reading a scope slot before the framework populates it; mixing up two RunScope instances (fresh one vs. the populated one); accidentally clearing/creating the scope mid-request so symbols from another scope are queried.

Related errors


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