phacility/phabricator · error · Exception

This request improperly specifies an MFA challenge token ("%

Error message

This request improperly specifies an MFA challenge token ("%s") multiple times and can not be processed.

What it means

The same parser in PhabricatorAuthChallenge::newChallengeResponsesFromRequest() rejects token lists where the same challenge PHID appears more than once: after exploding each element into phid/token it checks isset($token_map[$phid]) and throws, interpolating the duplicated PHID into the message. One challenge may only be answered once per request.

Source

Thrown at src/applications/auth/storage/PhabricatorAuthChallenge.php:86

      if (!strlen($token_element)) {
        continue;
      }

      // NOTE: This error message is intentionally not printing the token to
      // avoid disclosing it. As a result, it isn't terribly useful, but no
      // normal user should ever end up here.
      if (!preg_match('/^[^:]+:/', $token_element)) {
        throw new Exception(
          pht(
            'This request included an improperly formatted MFA challenge '.
            'token and can not be processed.'));
      }

      list($phid, $token) = explode(':', $token_element, 2);

      if (isset($token_map[$phid])) {
        throw new Exception(
          pht(
            'This request improperly specifies an MFA challenge token ("%s") '.
            'multiple times and can not be processed.',
            $phid));
      }

      $token_map[$phid] = new PhutilOpaqueEnvelope($token);
    }

    $challenges = mpull($challenges, null, 'getPHID');

    $now = PhabricatorTime::getNow();
    foreach ($challenges as $challenge_phid => $challenge) {
      // If the response window has expired, don't attach the token.
      if ($challenge->getResponseTTL() < $now) {
        continue;
      }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Submit each challenge token exactly once per request - remove duplicate mfa inputs
  2. Reload the MFA prompt from the normal UI to get a clean form with one input per challenge
  3. If you build the client, deduplicate elements by PHID before sending (keep the newest)
Defensive patterns

Strategy: validation

Validate before calling

// Deduplicate mfa elements by challenge PHID before submitting:
$map = array();
foreach ($submitted_mfa as $element) {
  $element = trim($element, ' ,');
  if (!strlen($element)) { continue; }
  list($phid, ) = explode(':', $element, 2);
  $map[$phid] = $element; // one response per challenge, last one wins
}
$submitted_mfa = array_values($map);

Try / catch

try {
  $responses = PhabricatorAuthChallenge::newChallengeResponsesFromRequest(
    $challenges, $request);
} catch (Exception $ex) {
  // Duplicate or malformed challenge tokens: 400 and restart flow.
  return new Aphront400Response();
}

Prevention

When it happens

Trigger: A request submits two mfa elements for the same challenge, e.g. mfa[]=PHID-CHAL-aaa:tok1 together with mfa[]=PHID-CHAL-aaa:tok2 - duplicated hidden inputs, a buggy double-submit that merges two forms, or crafted parameters.

Common situations: Client JS appending a second response for an already-answered challenge; form duplication from back/forward navigation; scripts replaying a response token plus a replacement token for the same challenge.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/a3d0e9b5b4395f4d. Report an issue: GitHub.