{"record":{"id":"1af2ed08dd00a973","repo":"theonedev/onedev","slug":"cannot-delete-primary-email-address-of-externally","errorCode":null,"errorMessage":"Cannot delete primary email address of externally authenticated user","messagePattern":"Cannot delete primary email address of externally authenticated user","errorType":"http","errorClass":"ExplicitException","httpStatus":400,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/EmailAddressResource.java","lineNumber":142,"sourceCode":"\t\t\tthrow new ExplicitException(\"Unable to send verification email as mail service is not configured\");\n\t\tif (emailAddress.isVerified())\n\t\t\tthrow new ExplicitException(\"Unable to send verification email as this email address is already verified\");\n\t\t\n\t\temailAddressService.sendVerificationEmail(emailAddress);\n\t\t\n\t\treturn emailAddressId;\n\t}\n\t\n\t@Api(order=300)\n\t@Path(\"/{emailAddressId}\")\n\t@DELETE\n\tpublic Response deleteEmailAddress(@PathParam(\"emailAddressId\") Long emailAddressId) {\n\t\tvar emailAddress = emailAddressService.load(emailAddressId);\n\t\tif (!SecurityUtils.isAdministrator() && !emailAddress.getOwner().equals(getAuthUser())) \n\t\t\tthrow new UnauthorizedException();\n\t\t\n\t\tif (emailAddress.isPrimary() && emailAddress.getOwner().getPassword() == null) {\n\t\t\tthrow new ExplicitException(\"Cannot delete primary email address of \"\n\t\t\t\t\t+ \"externally authenticated user\");\n\t\t}\n\t\tif (emailAddress.getOwner().getEmailAddresses().size() == 1)\n\t\t\tthrow new ExplicitException(\"At least one email address should be present for a user\");\n\t\temailAddressService.delete(emailAddress);\n\n\t\tif (!getAuthUser().equals(emailAddress.getOwner())) \n\t\t\tauditService.audit(null, \"deleted email address \\\"\" + emailAddress.getValue() + \"\\\" from account \\\"\" + emailAddress.getOwner().getName() + \"\\\" via RESTful API\", null, null);\n\n\t\treturn Response.ok().build();\n\t}\n\t\n}\n","sourceCodeStart":124,"sourceCodeEnd":156,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/EmailAddressResource.java#L124-L156","documentation":"deleteEmailAddress refuses to remove a user's primary email address when the account has no local password, i.e. it is authenticated externally (SSO/LDAP). The primary address is the account identity for such users, so deleting it would leave the externally-authenticated account without a resolvable email. It throws ExplicitException, which is surfaced as a user-facing message.","triggerScenarios":"DELETE /~api/emailAddresses/{id} where emailAddress.isPrimary() is true and emailAddress.getOwner().getPassword() == null (user authenticates via LDAP/SSO instead of a OneDev password).","commonSituations":"Users synchronized from LDAP or logging in via OAuth/SSO whose only stable email is the primary one; automation scripts bulk-pruning addresses that hit the primary of an SSO account.","solutions":["Delete a non-primary address instead, or add another address first.","For an externally authenticated user, update the email at the identity provider (LDAP/OAuth source) rather than in OneDev.","Convert the user to password (local) authentication if you truly need to change their primary address locally.","As admin, manage the account via the UI which offers clearer guidance for external accounts."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// skip primary address of externally authenticated users\nif (address.isPrimary() && address.getOwner().getPassword() == null) {\n    log.info(\"Skipping primary address of external user \" + address.getOwner().getName());\n    return;\n}","typeGuard":null,"tryCatchPattern":"try { client.deleteEmailAddress(id); }\ncatch (ExplicitException e) { /* expected for primary/external/last address — treat as skip */ }","preventionTips":["Check isPrimary() and owner password state before deleting.","Manage SSO/LDAP user emails at the identity provider, not via OneDev API.","Filter external-authenticated accounts out of bulk address-pruning jobs."],"tags":["rest-api","email","external-authentication","sso"],"backgroundTag":"invalid-state-transition","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}