mastra-ai/mastra · error · Error

Duplicate Subconscious ${phase} agent: ${name}

Error message

Duplicate Subconscious ${phase} agent: ${name}

What it means

assertUniqueNames rejects duplicate names among the Subconscious observation/reflection agent entries. Names are the identity used for bookkeeping and cursor scoping (e.g. CURATION_AGENT), so duplicates are ambiguous and throw at construction time. The message includes the phase (observation/reflection) and the offending name.

Source

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

 * Curation walks a worklist that can reach hundreds of records, and its completion marker is
 * fail-closed: a curator that runs out of steps advances no cursor at all. It gets a much larger
 * default budget than the other agents, which each handle a single bounded prompt.
 */
const DEFAULT_MAX_STEPS_BY_AGENT: Record<string, number> = { curate: 200 };
const MAX_MAX_STEPS = 500;
const DEFAULT_RECENT_UPDATES = 10;
const MAX_RECENT_UPDATES = 100;

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,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Rename one of the duplicate entries so names are unique within each phase.
  2. Deduplicate or merge config arrays before constructing Subconscious.
  3. If two agents genuinely differ, give them distinct descriptive names.

Example fix

// before
new Subconscious({ observation: [{ name: 'watch', model: a }, { name: 'watch', model: b }] })
// after
new Subconscious({ observation: [{ name: 'watch-a', model: a }, { name: 'watch-b', model: b }] })
Defensive patterns

Strategy: validation

Validate before calling

const names = [...observation, ...reflection].map(e => typeof e === 'string' ? e : e?.name);
const dupes = names.filter((n, i) => n && names.indexOf(n) !== i);
if (dupes.length) throw new Error(`Duplicate Subconscious agent names: ${[...new Set(dupes)].join(', ')}`);

Try / catch

try {
  const sub = new Subconscious(config);
} catch (err) {
  if (err.message.startsWith('Duplicate Subconscious')) {
    throw new ConfigError(`Subconscious config has duplicate agent names: ${err.message}`);
  } else throw err;
}

Prevention

When it happens

Trigger: Constructing Subconscious with two entries in the same phase sharing a name, e.g. observation: ['observe', { name: 'observe', model: x }] or two reflection entries both named 'reflect'.

Common situations: Merging config arrays from defaults and user overrides without deduplication; copy-pasted entries with the same name but different options; spreading multiple config sources into one array.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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