mem0ai/mem0 · error · Error

At least one entity ID is required for deleteEntities.

Error message

At least one entity ID is required for deleteEntities.

What it means

Thrown by PlatformBackend.deleteEntities when the EntityIds options object contains none of userId, agentId, appId, or runId. The v2 entity endpoint is path-based (/v2/entities/{entity_type}/{entity_id}/), so at least one entity id is required to build a URL; the guard fires before any HTTP call.

Source

Thrown at integrations/openclaw/backend/platform.ts:276

      return (await this._request(
        "DELETE",
        `/v1/memories/${memoryId}/`,
      )) as Record<string, unknown>;
    }
    throw new Error("Either memoryId or --all is required");
  }

  async deleteEntities(opts: EntityIds): Promise<Record<string, unknown>> {
    // v2 endpoint: DELETE /v2/entities/{entity_type}/{entity_id}/
    const typeMap: [string, string | undefined][] = [
      ["user", opts.userId],
      ["agent", opts.agentId],
      ["app", opts.appId],
      ["run", opts.runId],
    ];
    const entities = typeMap.filter(([, v]) => v) as [string, string][];
    if (entities.length === 0) {
      throw new Error("At least one entity ID is required for deleteEntities.");
    }
    // Delete each provided entity via the v2 path-based endpoint
    let result: Record<string, unknown> = {};
    for (const [entityType, entityId] of entities) {
      result = (await this._request(
        "DELETE",
        `/v2/entities/${entityType}/${entityId}/`,
      )) as Record<string, unknown>;
    }
    return result;
  }

  async ping(): Promise<Record<string, unknown>> {
    return (await this._request("GET", "/v1/ping/")) as Record<string, unknown>;
  }

  async status(
    _opts: { userId?: string; agentId?: string } = {},

View on GitHub (pinned to 001c235229)

Solutions

  1. Supply at least one entity id: deleteEntities({ userId: 'alice' }) — you may pass several and each is deleted sequentially.
  2. Check the ids you are passing are non-empty strings; trim user input before constructing EntityIds.
  3. If you meant to flush everything, that is a different operation: use delete(undefined, { all: true, ... }) instead.

Example fix

// before
await backend.deleteEntities({ userId, agentId }); // both undefined

// after
const ids = { userId, agentId };
if (!Object.values(ids).some(Boolean)) {
  throw new Error('no entity ids resolved — nothing to delete');
}
await backend.deleteEntities(ids);
Defensive patterns

Strategy: validation

Validate before calling

function hasEntityIds(ids: Partial<Record<'userId'|'agentId'|'appId'|'runId', string>>) {
  return Object.values(ids).some((v) => typeof v === 'string' && v.trim().length > 0);
}

Prevention

When it happens

Trigger: Calling deleteEntities({}) or deleteEntities({ userId: '' }) — empty strings are falsy and filtered out by the typeMap; passing an object with only undefined fields.

Common situations: Agent flows that build entity filters dynamically and end up with all-undefined ids; CLI delete-entities command invoked with no entity flags; copy-paste from the entities() listing that forgets to map ids into the call.

Related errors


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