mastra-ai/mastra · error
Message ${cursor} has no visible content (it may be an inter
Error message
Message ${cursor} has no visible content (it may be an internal system message). Try a neighboring message ID instead. What it means
After resolving the cursor message, the reader formats its visible parts; if the message yields zero visible parts (content is a bare string with no parts, or all parts are internal `data-*` parts such as tool/internal metadata), it throws this error directing the caller to a neighboring message. Internal system messages are stored but not meant to be surfaced as recall anchors.
Source
Thrown at packages/memory/src/tools/om-tools.ts:811
if (!threadId) {
throw new Error('Thread ID is required for recall');
}
const resolved = await resolveCursorMessage(memory, cursor, {
resourceId,
threadScope,
enforceThreadScope: false,
});
if ('hint' in resolved) {
throw new Error(resolved.hint);
}
const allParts = formatMessageParts(resolved, 'high');
if (allParts.length === 0) {
throw new Error(
`Message ${cursor} has no visible content (it may be an internal system message). Try a neighboring message ID instead.`,
);
}
const target = [...allParts].reverse().find(p => p.partIndex === partIndex);
if (!target) {
const availableIndices = allParts.map(p => p.partIndex).join(', ');
const highestVisiblePartIndex = Math.max(...allParts.map(p => p.partIndex));
if (partIndex > highestVisiblePartIndex) {
const nextMessage = await getNextVisibleMessage({
memory,
threadId,
resourceId,
after: resolved.createdAt,
});
View on GitHub (pinned to 75dd419e61)
Solutions
- Choose a message ID that appeared in visible recall output (user/assistant text) instead of one from raw storage.
- Use the previous or next message in the thread as the cursor, as the error suggests.
- List the thread with recall detail="low" to get only visible message IDs, then pick one.
- If this happens persistently, inspect the message content shape — a schema/migration may have stripped parts.
Example fix
// before
const cursor = allMessageIds[0]; // may be an internal system message
await recallDetail({ memory, threadId, cursor, partIndex: 0 });
// after
const visible = JSON.parse((await recallMessages({ memory, threadId, page: 1 })).messages);
const cursor = visible[0].messageId;
await recallDetail({ memory, threadId, cursor, partIndex: 0 }); Defensive patterns
Strategy: fallback
Try / catch
try {
return await recallDetail({ memory, threadId, cursor, partIndex });
} catch (e) {
if (e instanceof Error && e.message.includes('has no visible content')) {
// step to a neighboring message and retry once
const page = await recallMessages({ memory, threadId, page: 1, limit: 50 });
const msgs = JSON.parse(page.messages);
const idx = msgs.findIndex(m => m.messageId === cursor);
const neighbor = msgs[idx + 1] ?? msgs[idx - 1];
if (neighbor) return recallDetail({ memory, threadId, cursor: neighbor.messageId, partIndex });
}
throw e;
} Prevention
- Pick cursors from visible (user/assistant) messages in recall output, not raw storage IDs.
- Skip index-0 cursors in threads seeded with system messages.
- If a formerly valid cursor goes empty, suspect a schema/migration change to message parts.
When it happens
Trigger: Using a cursor that points to a system/internal message (e.g. a data-part-only message, an empty string-content message, or a tool-internal record) as the recall anchor; picking the last ID from storage metadata rather than from formatted recall output.
Common situations: Model picked a messageId that appeared in logs/storage but was filtered from visible recall output; threads seeded with system messages where index 0 is internal; cursors persisted from an older schema whose messages now format as empty.
Related errors
- Cursor is required
- Could not resolve cursor message: ${cursor}
- The cursor "${cursor}" looks like a range. Use one of the in
- AGENT_NETWORK_OBSERVATIONAL_MEMORY_UNSUPPORTED
- Observational memory record not found: ${currentRecord.id}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/fae659e6dee3134a.
Report an issue: GitHub.