n8n-io/n8n · error · BadRequestError
Request to delete a user failed because the user to delete a
Error message
Request to delete a user failed because the user to delete and the transferee are the same user
What it means
Thrown by DELETE /users/:id when the transferId query parameter equals the personal-project id of the user being deleted — i.e. the workflows/credentials would be transferred back to the same (personal) project being removed. HTTP 400. Fires after the existence and owner checks, after getPersonalProjectForUserOrFail resolves the to-be-deleted user's personal project.
Source
Thrown at packages/cli/src/controllers/users.controller.ts:257
relations: ['role'],
});
if (!userToDelete) {
throw new NotFoundError(
'Request to delete a user failed because the user to delete was not found in DB',
);
}
if (userToDelete.role.slug === GLOBAL_OWNER_ROLE.slug) {
throw new ForbiddenError('Instance owner cannot be deleted.');
}
const personalProjectToDelete = await this.projectRepository.getPersonalProjectForUserOrFail(
userToDelete.id,
);
if (transferId === personalProjectToDelete.id) {
throw new BadRequestError(
'Request to delete a user failed because the user to delete and the transferee are the same user',
);
}
let transfereeId;
let transfereeProject: Project | null = null;
if (transferId) {
transfereeProject = await this.projectRepository.findOneBy({ id: transferId });
if (!transfereeProject) {
throw new NotFoundError(
'Request to delete a user failed because the transferee project was not found in DB',
);
}
const transfereeProjectId = transfereeProject.id;
View on GitHub (pinned to 5ac6606e81)
Solutions
- Pass a transferId that belongs to a different user's personal project (or a shared project).
- If you have only the transferee user id, resolve their personal project first via GET /users/<transferee-id> and use that project id.
- Omit transferId entirely if you do not want to transfer (only do so if the user owns nothing).
Example fix
// before DELETE /users/123?transferId=<user-123-personal-project-id> // after DELETE /users/123?transferId=<user-456-personal-project-id>
Defensive patterns
Strategy: validation
Validate before calling
function pickTransferProject(targetUserPersonalProjectId: string, candidates: string[]) {
return candidates.find((p) => p !== targetUserPersonalProjectId)
?? (() => { throw new Error('transferee must differ from the deleted user'); })();
}
// pass a different user's personal project id as ?transferId= Try / catch
try { await fetch(`/rest/users/${id}?transferId=${pid}`, { method: 'DELETE' }); }
catch (e) { if (e.statusCode === 400 && /same user/.test(e.message)) { /* pick another project */ } else throw e; } Prevention
- transferId is a project id, not a user id.
- Resolve the transferee's personal project via GET /users/<transferee-id> and use that id.
- Ensure transferId != deleted user's personal project id.
When it happens
Trigger: DELETE /users/<id>?transferId=<that-user's-personal-project-id>. The transfer target resolves to the user's own personal project.
Common situations: UI defaulting the transferee picker to the same user; client computing transferId from the target user's profile; misunderstanding that transferId is a project id, not a user id, and passing the target's personal-project id.
Related errors
- Cannot delete your own user
- Request to delete a user failed because the transferee proje
- Request to delete a user failed because the user to delete w
- Invalid invite URL
- Invalid request
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/3aafa44969d738ec.
Report an issue: GitHub.