{"record":{"id":"6bc8843721fb55d1","repo":"phacility/phabricator","slug":"this-duo-enrollment-attempt-is-invalid-or-has-expi","errorCode":null,"errorMessage":"This Duo enrollment attempt is invalid or has expired (\"%s\"). Cancel the workflow and try again.","messagePattern":"This Duo enrollment attempt is invalid or has expired \\(\"(.+?)\"\\)\\. Cancel the workflow and try again\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/auth/factor/PhabricatorDuoAuthFactor.php","lineNumber":252,"sourceCode":"            return $this->newDuoConfig($user, $duo_user);\n          case 'waiting':\n            $waiting_icon = id(new PHUIIconView())\n              ->setIcon('fa-mobile', 'red');\n\n            $waiting_control = id(new PHUIFormTimerControl())\n              ->setIcon($waiting_icon)\n              ->setError(pht('Not Complete'))\n              ->appendChild(\n                pht(\n                  'You have not activated this enrollment in the Duo '.\n                  'application on your phone yet. Complete activation, then '.\n                  'click continue.'));\n\n            $form->appendControl($waiting_control);\n            break;\n          case 'invalid':\n          default:\n            throw new Exception(\n              pht(\n                'This Duo enrollment attempt is invalid or has '.\n                'expired (\"%s\"). Cancel the workflow and try again.',\n                $response));\n        }\n      }\n    }\n\n    if ($is_blocked) {\n      $blocked_icon = id(new PHUIIconView())\n        ->setIcon('fa-times', 'red');\n\n      $blocked_control = id(new PHUIFormTimerControl())\n        ->setIcon($blocked_icon)\n        ->appendChild(\n          pht(\n            'Your Duo account (\"%s\") has not completed Duo enrollment. '.\n            'Check your email and complete enrollment to continue.',","sourceCodeStart":234,"sourceCodeEnd":270,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/auth/factor/PhabricatorDuoAuthFactor.php#L234-L270","documentation":"Thrown inside PhabricatorDuoAuthFactor::processAddFactorForm() while finishing a Duo enrollment. When the user returns to the enrollment screen, Phabricator calls the Duo 'enroll_status' API with the user_id and activation_code stored in the MFA sync token; a 'success' response completes enrollment and 'waiting' re-renders the timer, but 'invalid' (or any unrecognized value) means the pending activation no longer exists on Duo's side, so the workflow aborts.","triggerScenarios":"Clicking Continue on the Duo activation-wait screen after the Duo enrollment has expired or been invalidated: the user did not activate in the Duo phone app within Duo's validity window, the activation was consumed or deleted in another session, or the enroll_status call returns an unexpected value because the provider credential/hostname point at the wrong Duo account.","commonSituations":"User starts enrollment, gets distracted, and clicks Continue minutes later; enrollment tab left open overnight; admin changed the Duo provider credential or hostname between start and finish; Duo returning unexpected payloads through a proxy.","solutions":["Cancel the enrollment workflow and start over; activate immediately in the Duo phone app after the pairing code appears, since pending Duo activations expire quickly.","Verify the provider's Duo API hostname and credential (Auth > Multi-Factor Auth) so enroll_status reaches the correct Duo integration.","Check network egress to *.duosecurity.com from the web host; MITM proxies can mangle status responses.","If every attempt fails instantly, recreate the Duo integration keys in the Duo admin panel and update the Passphrase credential."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pattern: treat any enroll_status other than 'success'/'waiting' as a\n// restart condition before rendering, instead of letting it fatal.\n$response = $result['response'];\nif (!in_array($response, array('success', 'waiting'), true)) {\n  return $this->newRestartEnrollmentControl($provider, $user);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return $factor->processAddFactorForm($provider, $form, $request, $user);\n} catch (Exception $ex) {\n  if (preg_match('/invalid or has expired/', $ex->getMessage())) {\n    // discard the MFA sync token and offer a fresh enrollment\n    return $this->newRestartEnrollmentDialog();\n  }\n  throw $ex;\n}","preventionTips":["Complete Duo activation in the phone app immediately after starting enrollment; pending activations expire within minutes.","Do not leave enrollment wait screens open across long delays or provider config changes.","Keep the Duo provider's credential and hostname stable while users are mid-enrollment.","Treat enroll_status 'invalid' as a user-recoverable state: cancel and restart, never retry the same activation."],"tags":["duo","mfa","enrollment","phabricator"],"backgroundTag":"mfa-enrollment-expired","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}