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
- Ensure the curator model reliably emits <curation-complete through="<recordId>"/> exactly once at the end; use a stronger model.
- Check that maxSteps/token limits are not truncating the curator output before the marker.
- Keep DEFAULT_INSTRUCTIONS intact if customizing instructions, or re-add the curation-complete protocol.
- 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
- Use a capable model for the curator and keep the curation-complete protocol instructions.
- Raise maxSteps/token budget so output is not truncated before the marker.
- Monitor for repeated failures — a recurring throw signals prompt/model drift.
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
- Extractor "${extractor.slug}" output did not match its schem
- ${EXTRACTED_VALUES_TAG} must contain a JSON object.
- Observer produced degenerate output after retry. ${describeD
- Multi-thread observer produced degenerate output after retry
- Learner did not acknowledge a valid reviewed record cursor.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/ff6675410854080f.
Report an issue: GitHub.