phacility/phabricator · info · PhabricatorMetaMTAReceivedMailProcessingException

err:duplicate

err:duplicate

Error message

Ignoring email with "Message-ID" hash "%s" that has been seen %d times, including this message.

What it means

dropMailAlreadyReceived() drops inbound mail whose normalized 'Message-ID' hash has already been recorded (STATUS_DUPLICATE): the code counts prior received mails with the same getMessageIDHash() and throws once this copy is not the first. Duplicate suppression is what makes Reply-All and multi-copy delivery safe — the same message hitting several inbound addresses is processed once. Duplicate status is also excluded from bounce emails.

Source

Thrown at src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php:411

      return;
    }

    $first_message = reset($messages);
    if ($first_message->getID() == $this->getID()) {
      // If this is the first copy of the message, it is okay to process it.
      // We may not have been able to to process it immediately when we received
      // it, and could may have received several copies without processing any
      // yet.
      return;
    }

    $message = pht(
      'Ignoring email with "Message-ID" hash "%s" that has been seen %d '.
      'times, including this message.',
      $message_id_hash,
      $messages_count);

    throw new PhabricatorMetaMTAReceivedMailProcessingException(
      MetaMTAReceivedMailStatus::STATUS_DUPLICATE,
      $message);
  }

  private function dropEmptyMail() {
    $body = $this->getCleanTextBody();
    $attachments = $this->getAttachments();

    if (strlen($body) || $attachments) {
      return;
    }

    // Only send an error email if the user is talking to just Phabricator.
    // We can assume if there is only one "To" address it is a Phabricator
    // address since this code is running and everything.
    $is_direct_mail = (count($this->getToAddresses()) == 1) &&
                      (count($this->getCCAddresses()) == 0);

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Treat STATUS_DUPLICATE as benign in most cases — check MetaMTA > Received Mail and confirm the first copy was processed successfully.
  2. If you need a genuine second submission, send a fresh message (new Message-ID) rather than resending/forwarding the identical one.
  3. If a whole queue got marked duplicate after a crash, inspect whether the FIRST copy was processed; if not, requeue that original.
  4. Admins: verify inbound routing does not fan one message out to multiple Phabricator receive addresses if per-copy processing matters.

Example fix

// before: same Message-ID delivered to two Phabricator addresses
// copy 1 -> processed; copy 2 -> err:duplicate, dropped

// after (if both actions are truly wanted): send two separate messages
// each with its own Message-ID, addressed to the intended object
Defensive patterns

Strategy: try-catch

Validate before calling

// Before submitting, check the Message-ID has not been seen (mirrors dropMailAlreadyReceived):
$hash = PhabricatorMetaMTAReceivedMail::hashMessageID($message_id);
$seen = id(new PhabricatorMetaMTAReceivedMailQuery())
  ->setViewer($viewer)
  ->withMessageIDHashes(array($hash))
  ->execute();
if ($seen) { /* already ingested once: skip */ }

Try / catch

try {
  $received_mail->processIncomingMail($sender);
} catch (PhabricatorMetaMTAReceivedMailProcessingException $ex) {
  if ($ex->getStatusCode() === MetaMTAReceivedMailStatus::STATUS_DUPLICATE) {
    // verify the FIRST copy succeeded, then treat as done — never blind-retry
    return;
  }
  throw $ex;
}

Prevention

When it happens

Trigger: Processing a received mail whose Message-ID hash already appears in the received-mail table with a processed ancestor. Happens when the MTA delivers one message to multiple Phabricator addresses (To: D123+...@ and CC: bugs@), when a user forwards/re-sends a message keeping the same Message-ID, or when a queue redelivers after a crash.

Common situations: Reply-all to a thread with two Phabricator addresses (expected and harmless — first receiver wins); mail server retry delivering the same message; users dragging the same message into a mail-to-ticket address twice; monitoring that resubmits mail with a stable Message-ID.

Related errors


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