mastra-ai/mastra · error · Error

Harness pending item "${pendingItemId}" was not found on ses

Error message

Harness pending item "${pendingItemId}" was not found on session "${sessionId}"

What it means

`updatePendingItem` maps over the session's pending items looking for one whose id matches `pendingItemId`; if none matched after the full pass, it throws this error. The session existed, but the specific pending item did not.

Source

Thrown at packages/core/src/storage/domains/harness/base.ts:75

      throw new Error(`Harness session "${sessionId}" was not found`);
    }

    let found = false;
    const pending = (record.pending ?? []).map(item => {
      if (item.id !== pendingItemId) return item;
      found = true;
      return {
        ...item,
        ...updates,
        id: item.id,
        sessionId: item.sessionId,
        createdAt: item.createdAt,
        updatedAt: new Date(),
      };
    });

    if (!found) {
      throw new Error(`Harness pending item "${pendingItemId}" was not found on session "${sessionId}"`);
    }

    return this.updateSession(sessionId, { pending });
  }

  async removePendingItem(sessionId: string, pendingItemId: string): Promise<SessionRecord> {
    const record = await this.loadSession(sessionId);
    if (!record) {
      throw new Error(`Harness session "${sessionId}" was not found`);
    }

    return this.updateSession(sessionId, {
      pending: (record.pending ?? []).filter(item => item.id !== pendingItemId),
    });
  }
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check that the pending item exists (`loadSession` then inspect `record.pending`) before updating.
  2. Verify `pendingItemId` comes from the same session's `appendPendingItem` result.
  3. Handle the already-removed case gracefully: treat item-not-found as a no-op in idempotent workflows.
  4. Log session id plus item id together to catch cross-session id reuse.

Example fix

// before
await storage.updatePendingItem(sessionId, itemId, { status: 'done' }); // throws if removed
// after
const rec = await storage.loadSession(sessionId);
if (rec?.pending?.some(i => i.id === itemId)) {
  await storage.updatePendingItem(sessionId, itemId, { status: 'done' });
}
Defensive patterns

Strategy: validation

Validate before calling

const record = await storage.loadSession(sessionId);
if (!record?.pending?.some(i => i.id === pendingItemId)) {
  return; // nothing to update
}
await storage.updatePendingItem(sessionId, pendingItemId, updates);

Type guard

function hasPendingItem(r: SessionRecord | null, itemId: string): r is SessionRecord {
  return r != null && Array.isArray(r.pending) && r.pending.some(i => i.id === itemId);
}

Try / catch

try {
  await storage.updatePendingItem(sessionId, itemId, updates);
} catch (e) {
  if (e instanceof Error && e.message.includes('pending item') && e.message.includes('was not found')) {
    return; // already removed — treat as no-op in idempotent flows
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `updatePendingItem` with a pendingItemId that was never appended, was already removed via `removePendingItem`, or belongs to a different session.

Common situations: Updating an item after it was finalized/removed by the harness; mixing item ids across sessions; double-processing where one worker already removed the item it completed; copy-paste of item id from logs of another session.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/e888e22c37bad9ba. Report an issue: GitHub.