mem0ai/mem0 · error · APIError

Failed to delete ${entity.type} ${entity.name}: ${error.mess

Error message

Failed to delete ${entity.type} ${entity.name}: ${error.message}

What it means

During the per-entity deletion loop in deleteUsers(), any failure of the DELETE call to /v2/entities/{type}/{name}/ is wrapped as APIError('Failed to delete {type} {name}: {message}'). The loop is not error-tolerant: the first failing entity aborts the whole run, and entities before it have already been deleted — the operation is intentionally not transactional.

Source

Thrown at mem0-ts/src/client/mem0.ts:574

    }

    if (to_delete.length === 0) {
      throw new Error("No entities to delete");
    }

    for (const entity of to_delete) {
      try {
        // fetch() reuses the pooled connection; axios here defaulted to
        // keepAlive: false, one handshake per entity.
        await this._fetchWithErrorHandling(
          `${this.host}/v2/entities/${encodePathSegment(entity.type)}/${encodePathSegment(entity.name)}/`,
          {
            method: "DELETE",
            headers: this.headers,
          },
        );
      } catch (error: any) {
        throw new APIError(
          `Failed to delete ${entity.type} ${entity.name}: ${error.message}`,
        );
      }
    }

    this._captureEvent("delete_users", [
      { userId, agentId, appId, runId, sync_type: "sync" },
    ]);

    return {
      message:
        userId || agentId || appId || runId
          ? "Entity deleted successfully."
          : "All users, agents, apps and runs deleted.",
    };
  }

  async batchUpdate(memories: Array<MemoryUpdateBody>): Promise<string> {

View on GitHub (pinned to 001c235229)

Solutions

  1. Read the entity name and inner message from the error to retry just the remaining entities idempotently (DELETE is idempotent).
  2. Pre-empt rate limits by chunking or throttling the delete run.
  3. For resumable wipes, track deleted entities externally and continue from the failed one.
  4. Re-fetch users() after a failure to reconcile actual remaining state before retrying.

Example fix

// before
await client.deleteUsers({}); // one failure aborts the run

// after
for (const u of (await client.users()).results) {
  try {
    await client.deleteUsers({ userId: u.name });
  } catch (e) {
    console.error(`skipped ${u.name}:`, (e as Error).message); // continue, reconcile later
  }
}
Defensive patterns

Strategy: try-catch

Type guard

const isEntityDeleteError = (e: unknown): { type: string; name: string } | null => {
  const m = /Failed to delete (\S+) (.+?):/.exec((e as Error).message ?? '');
  return m ? { type: m[1], name: m[2] } : null;
};

Try / catch

try {
  await client.deleteUsers({});
} catch (e) {
  const failed = isEntityDeleteError(e);
  if (failed) {
    // DELETE is idempotent: re-fetch remaining entities and resume from the failed one
    const remaining = (await client.users()).results;
    for (const u of remaining) {
      if (u.type === failed.type && u.name === failed.name) {
        await client.deleteUsers({ userId: u.name } as any); // or matching scope
      }
    }
  }
  throw e;
}

Prevention

When it happens

Trigger: Bulk deleteUsers() where one entity's DELETE returns an error (already deleted by a concurrent process, permission revoked mid-run, transient 5xx, entity name with characters that changed meaning after URL encoding). The thrown message names the exact entity and the underlying error.

Common situations: Long bulk wipes interrupted by rate limits (429) partway through; concurrent deleters racing; partial retries re-hitting already-removed entities.

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/622288febe646399. Report an issue: GitHub.