TencentCloud/TencentDB-Agent-Memory · error · MetadataError
last_system_admin
last_system_admin
Error message
cannot delete the last system_admin user
What it means
MetadataError 'last_system_admin' from deleteUsersForCaller: the batch would delete every remaining system_admin, leaving the system without admin governance. The service counts admins (countSystemAdmins) and refuses when totalAdmins - deletingSystemAdmins < 1.
Source
Thrown at MemoryCore/src/metadata/service/metadata-service.ts:526
return this.store.getUserByKey(userKey);
}
async getUserByExternalId(authProvider: string, externalId: string): Promise<UserEntity | null> {
return this.store.getUserByExternalId(authProvider, externalId);
}
async deleteUsersForCaller(userIds: string[], ctx: V3AuthContext): Promise<BatchDeleteResult> {
if (!canManageUsers(ctx)) {
throw new MetadataError("permission_denied", "user management requires system admin");
}
let deletingSystemAdmins = 0;
for (const id of userIds) {
const u = await this.getUserById(id);
if (u && isSystemAdminUser(u)) deletingSystemAdmins++;
}
const totalAdmins = await this.store.countSystemAdmins();
if (totalAdmins > 0 && totalAdmins - deletingSystemAdmins < 1) {
throw new MetadataError("last_system_admin", "cannot delete the last system_admin user");
}
return this.deleteUsers(userIds);
}
async deleteUsers(userIds: string[]): Promise<BatchDeleteResult> {
return this.store.deleteUsers(userIds);
}
async listUsersForCaller(
input: { team_id?: string } & UserListFilter,
ctx: V3AuthContext,
pagination: PaginationParams,
): Promise<PaginatedResult<UserPublic>> {
const filtersPresent = !!(input.user_ids?.length || input.username);
const storeFilter = this.buildUserListStoreFilter(input);
if (!input.team_id) {
if (!ctx.isSystemAdmin) {View on GitHub (pinned to 3efcd317b8)
Solutions
- Remove the system_admin id(s) from the deletion batch and keep at least one admin
- Promote another user to system_admin first, then delete the original
- Filter the batch: skip ids where isSystemAdminUser(u) is true when totalAdmins === 1
Example fix
// before await svc.deleteUsersForCaller([adminId, u1, u2], ctx); // throws last_system_admin // after const deletable = [u1, u2]; // exclude the last system_admin await svc.deleteUsersForCaller(deletable, ctx);
Defensive patterns
Strategy: validation
Validate before calling
const totalAdmins = await store.countSystemAdmins();
const adminDeletes = 0;
for (const id of userIds) {
const u = await svc.getUserById(id);
if (u && isSystemAdminUser(u)) adminDeletes++;
}
if (totalAdmins > 0 && totalAdmins - adminDeletes < 1) {
throw new Error('batch would remove the last system_admin');
} Type guard
function isDeletable(u: UserEntity | null, remainingAdmins: number): boolean {
return !(u && isSystemAdminUser(u) && remainingAdmins - 1 < 1);
} Try / catch
try {
await svc.deleteUsersForCaller(ids, ctx);
} catch (e) {
if (e instanceof MetadataError && e.code === 'last_system_admin') {
// retry excluding admin ids
} else throw e;
} Prevention
- Always exclude the last system_admin from bulk delete batches
- Promote a replacement admin before removing an admin account
- Audit cleanup scripts so bootstrap admin ids are never included
When it happens
Trigger: Calling deleteUsersForCaller with a batch that includes the only existing system_admin (e.g. ['admin-id']), or a batch whose admin deletions exhaust the admin pool.
Common situations: Cleanup scripts bulk-deleting stale accounts that include the bootstrap admin; deleting 'test' users where the bootstrap admin was actually in use; multi-tenant scripts iterating all user ids.
Related errors
- [sqlite] deleteL0BySession requires a non-empty sessionId
- clearMemoryContent requires non-empty teamId and agentId
AI-assisted analysis of TencentCloud/TencentDB-Agent-Memory@3efcd317b8 (2026-09-01).
Data as JSON: /api/errors/b2131730a960b7cd.
Report an issue: GitHub.