can1357/oh-my-pi · error · AIError.ValidationError
Cursor blob not found
Error message
Cursor blob not found
What it means
Cursor's AgentService protocol references prompt blobs by id; readCursorBlob looks the id up in the per-conversation in-memory blob store and throws ValidationError when nothing is stored under that hex key. The blob needed to reconstruct the request is missing, so the conversation cannot continue.
Source
Thrown at packages/ai/src/providers/cursor.ts:4564
if (output.usage.contextTokens !== usedTokens) {
output.usage.contextTokens = usedTokens;
}
}
function createBlobId(data: Uint8Array): Uint8Array {
return new Uint8Array(createHash("sha256").update(data).digest());
}
function storeCursorBlob(blobStore: Map<string, Uint8Array>, data: Uint8Array): Uint8Array {
const blobId = createBlobId(data);
blobStore.set(Buffer.from(blobId).toString("hex"), data);
return blobId;
}
function readCursorBlob(blobStore: Map<string, Uint8Array>, blobId: Uint8Array): Uint8Array {
const data = blobStore.get(Buffer.from(blobId).toString("hex"));
if (!data) {
throw new AIError.ValidationError("Cursor blob not found");
}
return data;
}
/**
* Cursor AgentService reconstructs the model prompt from `requestContext.rules`,
* not from the client-supplied `rootPromptMessagesJson` system blobs. Map each
* OMP system-prompt entry to a global CursorRule so always-apply rules survive
* that reconstruction.
*/
export function buildCursorRequestContextRules(systemPrompt: readonly string[] | undefined): CursorRule[] {
return normalizeSystemPrompts(systemPrompt).map((content, index) =>
create(CursorRuleSchema, {
fullPath: `/omp/system-prompt/${index}.mdc`,
content,
source: CursorRuleSource.USER,
type: create(CursorRuleTypeSchema, {
type: {View on GitHub (pinned to 9690622007)
Solutions
- Start a new conversation/session so blobs are written to a fresh store before being referenced.
- Keep the conversation and its blob store alive in the same process for the conversation's duration; persist blobs externally if sessions must survive restarts.
- Verify the blob id key encoding matches (hex string of the Uint8Array) on both write and read.
- Ensure conversationId rotation logic copies blob store entries to the rotated id.
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
if (!conversationBlobStores.get(conversationId)?.has(Buffer.from(blobId).toString("hex"))) {
// blob missing — start a fresh conversation instead of continuing
} Type guard
null
Try / catch
try {
await streamCursor(model, ctx, { conversationId, ...options });
} catch (err) {
if (err instanceof AIError.ValidationError && err.message === "Cursor blob not found") {
// restart with a new conversationId (fresh blob store)
return streamCursor(model, ctx, { conversationId: crypto.randomUUID(), ...options });
}
throw err;
} Prevention
- Persist blobs alongside conversation state if sessions must survive restarts.
- Keep conversation lifetime tied to its in-process blob store.
- Copy blob entries when rotating conversation ids.
When it happens
Trigger: Reading a blob id that was never written to the store for the current conversation — e.g. continuing a conversation whose blob store was discarded (process restart), referencing a blob from a different conversationId, or a stale/rotated conversation id mapping to a fresh empty Map.
Common situations: Server restart wiping the in-memory conversationBlobStores while conversation ids persist; resuming a session across processes; a blob id serialized/mismatched (hex vs raw bytes) so lookup misses.
Related errors
- Cursor ${targetModelId} cannot continue history from a diffe
- Invalid RPC message cursor
- stale_cursor
- Unsupported language '{value}'. Supported: {}
- Unable to infer language from file extension: {}. Specify `l
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/82f0c8af2c500aac.
Report an issue: GitHub.