mastra-ai/mastra · error · Error
Harness pending item "${item.id}" already exists on session
Error message
Harness pending item "${item.id}" already exists on session "${sessionId}" What it means
`appendPendingItem` throws this when the target session already contains a pending item with the same `item.id`. The library enforces unique pending-item ids per session to avoid duplicate work items.
Source
Thrown at packages/core/src/storage/domains/harness/base.ts:42
const next: SessionRecord = {
...record,
...updates,
id: record.id,
createdAt: record.createdAt,
lastActivityAt: updates.lastActivityAt ?? new Date(),
};
await this.saveSession(next);
return next;
}
async appendPendingItem(sessionId: string, item: HarnessPendingItemRecord): Promise<SessionRecord> {
const record = await this.loadSession(sessionId);
if (!record) {
throw new Error(`Harness session "${sessionId}" was not found`);
}
if (record.pending?.some(existing => existing.id === item.id)) {
throw new Error(`Harness pending item "${item.id}" already exists on session "${sessionId}"`);
}
return this.updateSession(sessionId, {
pending: [...(record.pending ?? []), item],
});
}
async updatePendingItem(
sessionId: string,
pendingItemId: string,
updates: Partial<Omit<HarnessPendingItemRecord, 'id' | 'sessionId' | 'createdAt'>>,
): Promise<SessionRecord> {
const record = await this.loadSession(sessionId);
if (!record) {
throw new Error(`Harness session "${sessionId}" was not found`);
}
let found = false;View on GitHub (pinned to 75dd419e61)
Solutions
- Generate a unique id per pending item (crypto.randomUUID() or an incrementing per-session counter).
- Check `record.pending` (via `loadSession`) for an existing item with the id before appending.
- Switch to `updatePendingItem` when the intent is to modify an existing item rather than add a new one.
- Make retry wrappers idempotent: catch this error and treat the append as already-done if the existing item matches.
Example fix
// before
await storage.appendPendingItem(sessionId, { id: 'tool-call', /* ... */ }); // throws on retry
// after
await storage.appendPendingItem(sessionId, { id: crypto.randomUUID(), /* ... */ }); Defensive patterns
Strategy: validation
Validate before calling
const record = await storage.loadSession(sessionId);
if (record?.pending?.some(i => i.id === item.id)) {
return; // already appended — idempotent no-op
}
await storage.appendPendingItem(sessionId, item); Type guard
function isPendingItem(x: unknown): x is HarnessPendingItemRecord {
return typeof x === 'object' && x !== null && typeof (x as any).id === 'string';
} Try / catch
try {
await storage.appendPendingItem(sessionId, item);
} catch (e) {
if (e instanceof Error && e.message.includes('already exists')) {
return; // treat as success for idempotent retries
}
throw e;
} Prevention
- Generate item ids with crypto.randomUUID() instead of derived/fixed strings.
- Design retries as idempotent: catch 'already exists' and continue.
- Use updatePendingItem when modifying an existing item, not append.
- Scope item ids to the session (prefix with sessionId if reused across sessions).
When it happens
Trigger: Calling `appendPendingItem(sessionId, item)` where `record.pending` already contains an entry whose `id === item.id` — typically retrying an append after a timeout, or a client generating non-unique ids.
Common situations: Idempotent retry logic that re-sends the same item without checking; crash-recovery replay of a message queue; code that constructs item ids from non-unique fields (timestamps at second granularity, fixed strings like 'plan').
Related errors
- EXPERIMENT_ID_CONFLICT
- Harness session "${sessionId}" was not found
- Harness pending item "${pendingItemId}" was not found on ses
- Harness session "${sessionId}" was not found
- MCP client with id ${mcpClient.id} already exists
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/5fe3557f35aa04e3.
Report an issue: GitHub.