mastra-ai/mastra · error · Error

Subconscious maxSteps must be an integer between 1 and ${MAX

Error message

Subconscious maxSteps must be an integer between 1 and ${MAX_MAX_STEPS}.

What it means

boundedSteps clamps/validates each Subconscious agent's maxSteps to an integer within [1, MAX_MAX_STEPS]. If a configured maxSteps is a non-integer, zero, negative, or above the hard cap, the constructor/resolver throws. This protects against runaway agent loops.

Source

Thrown at packages/memory/src/processors/observational-memory/subconscious/index.ts:46

function entryName(entry: string | { name: string }): string {
  return typeof entry === 'string' ? entry : entry.name.trim();
}

function assertUniqueNames(entries: Array<string | { name: string }>, phase: string): void {
  const seen = new Set<string>();
  for (const entry of entries) {
    const name = entryName(entry);
    if (!name) throw new Error(`Subconscious ${phase} agent name is required.`);
    if (seen.has(name)) throw new Error(`Duplicate Subconscious ${phase} agent: ${name}`);
    seen.add(name);
  }
}

function boundedSteps(entry: { maxSteps?: number } | undefined, fallback: number): number {
  const steps = entry?.maxSteps ?? fallback;
  if (!Number.isInteger(steps) || steps < 1 || steps > MAX_MAX_STEPS) {
    throw new Error(`Subconscious maxSteps must be an integer between 1 and ${MAX_MAX_STEPS}.`);
  }
  return steps;
}

function resolveExtractor(entry: SubconsciousObservationEntry): ResolvedSubconsciousAgent {
  const config = typeof entry === 'string' ? undefined : entry;
  const name = entryName(entry);
  return {
    name,
    instructions: config?.instructions,
    builtIn: name === 'capture',
  };
}

function resolveAgent(
  entry: string | { name: string; instructions?: string; model?: any; agent?: any; maxSteps?: number },
  builtIns: Set<string>,
  globalModel: SubconsciousConfig['model'],

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Set maxSteps to a positive integer within the allowed cap (check MAX_MAX_STEPS in the module).
  2. Coerce env/config values with Number() and validate Number.isInteger before constructing.
  3. Omit maxSteps to use the built-in fallback.

Example fix

// before
new Subconscious({ observation: [{ name: 'watch', maxSteps: 0 }] })
// after
new Subconscious({ observation: [{ name: 'watch', maxSteps: 5 }] })
Defensive patterns

Strategy: validation

Validate before calling

function assertBoundedSteps(n: unknown): asserts n is number {
  if (!Number.isInteger(n) || (n as number) < 1) throw new Error(`maxSteps must be an integer between 1 and ${MAX_MAX_STEPS}`);
}

Type guard

function isValidMaxSteps(n: unknown): n is number {
  return Number.isInteger(n) && n >= 1 && n <= MAX_MAX_STEPS;
}

Try / catch

try {
  const sub = new Subconscious(config);
} catch (err) {
  if (err.message.includes('maxSteps must be an integer')) {
    throw new ConfigError('Fix maxSteps in Subconscious config (integer within 1..MAX_MAX_STEPS)');
  } else throw err;
}

Prevention

When it happens

Trigger: Setting maxSteps: 0, maxSteps: -1, maxSteps: 2.5, or maxSteps exceeding MAX_MAX_STEPS on any observation/reflection agent entry, or on Subconscious defaults.

Common situations: Reading maxSteps from env/config files as strings or floats; copying examples that use very large loop counts; intending 'unlimited' and passing 0 or Infinity.

Related errors


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