mastra-ai/mastra · error

Curator did not acknowledge a valid processed…

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.

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.

Appendix: 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)