{"record":{"id":"031185723f6d514d","repo":"phacility/phabricator","slug":"email-record-has-invalid-user-phid","errorCode":null,"errorMessage":"Email record has invalid user PHID!","messagePattern":"Email record has invalid user PHID!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php","lineNumber":52,"sourceCode":"\n    $email = id(new PhabricatorUserEmail())->loadOneWhere(\n      'address = %s',\n      $address);\n    if (!$email) {\n      throw new PhutilArgumentUsageException(\n        pht(\n          'No email exists with address \"%s\"!',\n          $address));\n    }\n\n    $viewer = $this->getViewer();\n\n    $user = id(new PhabricatorPeopleQuery())\n      ->setViewer($viewer)\n      ->withPHIDs(array($email->getUserPHID()))\n      ->executeOne();\n    if (!$user) {\n      throw new Exception(pht('Email record has invalid user PHID!'));\n    }\n\n    $editor = id(new PhabricatorUserEditor())\n      ->setActor($viewer)\n      ->verifyEmail($user, $email);\n\n    $console = PhutilConsole::getConsole();\n\n    $console->writeOut(\n      \"%s\\n\",\n      pht('Done.'));\n\n    return 0;\n  }\n\n}\n","sourceCodeStart":34,"sourceCodeEnd":69,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php#L34-L69","documentation":"Thrown by `bin/auth verify` when the email row exists but its userPHID column does not resolve to any real user. After loading the PhabricatorUserEmail record, the workflow queries PhabricatorPeopleQuery with that PHID; a null result raises this generic Exception (not a usage exception), because the cause is data corruption rather than operator input: an email record pointing at a missing user. The verification editor is never invoked, so nothing is written.","triggerScenarios":"Running `bin/auth verify <address>` where the user_email row references a PHID of a deleted/purged user, a PHID mangled by a partial import or manual SQL edit, or a user record removed while their email rows survived.","commonSituations":"Users were deleted with `bin/remove destroy` but orphaned user_email rows remained; a database migration or restore left referential integrity broken; someone edited user rows by hand in production.","solutions":["Inspect the orphan: `SELECT e.phid, e.address, e.userPHID FROM user_email e LEFT JOIN user u ON u.phid = e.userPHID WHERE e.address = '<address>';` — the join will show NULL on the user side.","If the user was deleted intentionally, remove the orphaned email row (or use the proper user-removal workflow to purge it), since the address can no longer be verified for anyone.","If the user should exist, repair the userPHID to point at the correct user row and re-run `bin/auth verify <address>`.","Audit for more orphans with `SELECT e.userPHID FROM user_email e LEFT JOIN user u ON u.phid=e.userPHID WHERE u.phid IS NULL;`."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-flight: detect the orphan before invoking the workflow\n$user = id(new PhabricatorPeopleQuery())\n  ->setViewer(PhabricatorUser::getOmnipotentUser())\n  ->withPHIDs(array($email->getUserPHID()))\n  ->executeOne();\nif (!$user) {\n  // orphaned email row: repair or delete it before running verify\n}","typeGuard":null,"tryCatchPattern":"try {\n  $err = id(new PhabricatorUserEditor())\n    ->setActor($viewer)\n    ->verifyEmail($user, $email);\n} catch (Exception $ex) {\n  // 'Email record has invalid user PHID!' means data corruption:\n  // log it, halt the batch, and queue a manual repair of user_email.userPHID\n}","preventionTips":["Never delete user rows with raw SQL; use Phabricator's removal workflows so dependent rows are purged.","Periodically audit for orphaned user_email rows via LEFT JOIN on user.phid.","Back up and verify referential integrity after imports, migrations, and restores."],"tags":["phabricator","cli","email","data-corruption","orphaned-record"],"backgroundTag":"dangling-foreign-key","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}