mastra-ai/mastra · error

Curator did not acknowledge a valid processed KnowledgeRecor

Error message

Curator did not acknowledge a valid processed KnowledgeRecord cursor.

What it means

After the curator LLM finishes, curate scans the model's text for a <curation-complete through="..."/> marker and validates it against the worklist of KnowledgeRecords. If the marker is missing, malformed, or names a record id not present in this batch, it throws, refusing to advance the curation cursor. This prevents silent data loss where records would be skipped forever.

Source

Thrown at packages/memory/src/processors/observational-memory/subconscious/curate.ts:108

      );
      const result = await agent.generate(
        `Parent thread: ${context.parentThreadId}\nCurrent time: ${new Date().toISOString()}\nWorklist truncated: ${worklist.hasMore}\n\nCommitted pre-reflection observations:\n${context.observations}\n\nNew KnowledgeRecord worklist:\n${JSON.stringify(worklist.records)}`,
        {
          requestContext: context.requestContext,
          abortSignal: context.abortSignal,
          maxSteps: config.maxSteps,
          memory: {
            thread: `subconscious:${context.parentThreadId}:curate`,
            resource: context.resourceId,
          },
        },
      );

      if (worklist.records.length) {
        const markers = [...result.text.matchAll(/<curation-complete\s+through=["']([^"']+)["']\s*\/>/gi)];
        const acknowledgedId = markers.at(-1)?.[1];
        if (!acknowledgedId || !worklist.records.some(record => record.id === acknowledgedId)) {
          throw new Error('Curator did not acknowledge a valid processed KnowledgeRecord cursor.');
        }
        await store.advanceCurationCursor({
          sourceThreadId: context.parentThreadId,
          agent: CURATION_AGENT,
          lastKnowledgeId: acknowledgedId,
        });
      }
      return 'ran';
    } catch (error) {
      const message = `curate: ${error instanceof Error ? error.message : String(error)}`;
      await context.writer?.custom({ type: 'data-subconscious-error', data: { agent: 'curate', error: message } });
      if (store && scope) {
        await publishSubconsciousActivity({
          store,
          scope,
          recentUpdates: subconscious.activity === false ? 10 : subconscious.activity.recentUpdates,
          sendStateSignal: context.sendStateSignal,
          errors: [message],

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Ensure the curator model reliably emits <curation-complete through="<recordId>"/> exactly once at the end; use a stronger model.
  2. Check that maxSteps/token limits are not truncating the curator output before the marker.
  3. Keep DEFAULT_INSTRUCTIONS intact if customizing instructions, or re-add the curation-complete protocol.
  4. Retry the curation run; the cursor is not advanced on failure so the batch will be reprocessed.

Example fix

// before: custom instructions drop protocol
instructions: ['Curate the records.']
// after: include the protocol
instructions: [DEFAULT_INSTRUCTIONS, 'Finish with <curation-complete through="lastProcessedRecordId" />']
Defensive patterns

Strategy: retry

Type guard

function isValidAcknowledgment(text: string, recordIds: string[]): boolean {
  const ids = [...text.matchAll(/<curation-complete\s+through=["']([^"']+)["']\s*\/>/gi)].map(m => m[1]);
  return ids.length > 0 && recordIds.includes(ids.at(-1)!);
}

Try / catch

try {
  await curate(context);
} catch (err) {
  if (err.message.includes('did not acknowledge')) {
    logger.warn('curator output missing valid curation-complete marker; will retry batch');
    await scheduleCurationRetry(context.parentThreadId);
  } else throw err;
}

Prevention

When it happens

Trigger: The curator agent's output lacks the <curation-complete/> tag, uses the wrong attribute syntax, or emits a KnowledgeRecord id not in the current worklist (e.g. hallucinated id or stale record).

Common situations: Model too weak to follow the output protocol; custom/overridden curator instructions that drop the marker; model output truncated by maxSteps or token limits before emitting the tag; worklist changed between reads.

Related errors


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