{"record":{"id":"ff6675410854080f","repo":"mastra-ai/mastra","slug":"curator-did-not-acknowledge-a-valid-processed-know","errorCode":null,"errorMessage":"Curator did not acknowledge a valid processed KnowledgeRecord cursor.","messagePattern":"Curator did not acknowledge a valid processed KnowledgeRecord cursor\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/memory/src/processors/observational-memory/subconscious/curate.ts","lineNumber":108,"sourceCode":"      );\n      const result = await agent.generate(\n        `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)}`,\n        {\n          requestContext: context.requestContext,\n          abortSignal: context.abortSignal,\n          maxSteps: config.maxSteps,\n          memory: {\n            thread: `subconscious:${context.parentThreadId}:curate`,\n            resource: context.resourceId,\n          },\n        },\n      );\n\n      if (worklist.records.length) {\n        const markers = [...result.text.matchAll(/<curation-complete\\s+through=[\"']([^\"']+)[\"']\\s*\\/>/gi)];\n        const acknowledgedId = markers.at(-1)?.[1];\n        if (!acknowledgedId || !worklist.records.some(record => record.id === acknowledgedId)) {\n          throw new Error('Curator did not acknowledge a valid processed KnowledgeRecord cursor.');\n        }\n        await store.advanceCurationCursor({\n          sourceThreadId: context.parentThreadId,\n          agent: CURATION_AGENT,\n          lastKnowledgeId: acknowledgedId,\n        });\n      }\n      return 'ran';\n    } catch (error) {\n      const message = `curate: ${error instanceof Error ? error.message : String(error)}`;\n      await context.writer?.custom({ type: 'data-subconscious-error', data: { agent: 'curate', error: message } });\n      if (store && scope) {\n        await publishSubconsciousActivity({\n          store,\n          scope,\n          recentUpdates: subconscious.activity === false ? 10 : subconscious.activity.recentUpdates,\n          sendStateSignal: context.sendStateSignal,\n          errors: [message],","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/subconscious/curate.ts#L90-L126","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: custom instructions drop protocol\ninstructions: ['Curate the records.']\n// after: include the protocol\ninstructions: [DEFAULT_INSTRUCTIONS, 'Finish with <curation-complete through=\"lastProcessedRecordId\" />']","handlingStrategy":"retry","validationCode":null,"typeGuard":"function isValidAcknowledgment(text: string, recordIds: string[]): boolean {\n  const ids = [...text.matchAll(/<curation-complete\\s+through=[\"']([^\"']+)[\"']\\s*\\/>/gi)].map(m => m[1]);\n  return ids.length > 0 && recordIds.includes(ids.at(-1)!);\n}","tryCatchPattern":"try {\n  await curate(context);\n} catch (err) {\n  if (err.message.includes('did not acknowledge')) {\n    logger.warn('curator output missing valid curation-complete marker; will retry batch');\n    await scheduleCurationRetry(context.parentThreadId);\n  } else throw err;\n}","preventionTips":["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."],"tags":["llm-output","protocol-violation","observational-memory"],"backgroundTag":"llm-output-format-invalid","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}