{"record":{"id":"00b73d0adcc380ad","repo":"phacility/phabricator","slug":"request-failed-with-errors-s","errorCode":null,"errorMessage":"Request failed with errors: %s.","messagePattern":"Request failed with errors: (.+?)\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/metamta/adapter/PhabricatorMailMailgunAdapter.php","lineNumber":129,"sourceCode":"        $attachment->getData(),\n        $attachment->getFilename(),\n        $attachment->getMimeType());\n    }\n\n    list($body) = $future->resolvex();\n\n    $response = null;\n    try {\n      $response = phutil_json_decode($body);\n    } catch (PhutilJSONParserException $ex) {\n      throw new PhutilProxyException(\n        pht('Failed to JSON decode response.'),\n        $ex);\n    }\n\n    if (!idx($response, 'id')) {\n      $message = $response['message'];\n      throw new Exception(\n        pht(\n          'Request failed with errors: %s.',\n          $message));\n    }\n  }\n\n}\n","sourceCodeStart":111,"sourceCodeEnd":137,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/metamta/adapter/PhabricatorMailMailgunAdapter.php#L111-L137","documentation":"The Mailgun API answered with valid JSON, but the decoded object has no 'id' key - Mailgun only includes 'id' when a message is queued. The adapter therefore treats the response as a delivery failure and rethrows Mailgun's own 'message' field as the exception text. Note the code reads $response['message'] unconditionally, so a response with neither 'id' nor 'message' also produces an undefined-index error on top.","triggerScenarios":"sendMessage() through the mailgun adapter with: an API key belonging to a different account than the configured 'domain'; a 'from' address on a domain Mailgun has not verified for that account ('Sandbox subdomains are for test purposes only'); malformed or rejected recipients; suspended account/quota exhaustion - any JSON response lacking 'id'.","commonSituations":"Sandbox/test domain left in cluster.mailers after go-live while production mail uses a real 'from' domain; API key rotated in Mailgun but not in Phabricator; sender domain not (re)verified after DNS changes.","solutions":["Read the exception text - it is Mailgun's own error message and names the problem ('Domain not found: ...', 'Sandbox subdomains...', 'unauthorized', 401/403 messages).","Make sure the mailer's 'domain' and 'api-key' options belong to the same Mailgun account and the domain is verified (Mailgun dashboard, Sending > Domains).","Send from an address on the verified domain (or from the sandbox postmaster address when deliberately testing).","Check account status and quotas in the Mailgun dashboard if the message indicates limits or suspension."],"exampleFix":"// before: from-address on a domain Mailgun has not verified\n$mail->setFrom('no-reply@unverified-domain.net');\n\n// after: from-address on the verified sending domain\n$mail->setFrom('no-reply@mg.example.com');","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  $adapter->sendMessage($message);\n} catch (Exception $ex) {\n  $text = $ex->getMessage();\n  // The text is Mailgun's own 'message' field: classify it.\n  if (preg_match('/Domain not found|Sandbox subdomains|unauthorized/i', $text)) {\n    // permanent: stop retrying, alert the admin to fix domain/api-key\n    $message->setStatus(PhabricatorMailOutboundStatus::STATUS_FAIL);\n  } else {\n    throw $ex; // let the worker retry\n  }\n}","preventionTips":["Verify the Mailgun domain and from-address before switching a mailer to production.","Keep the Mailgun dashboard open when debugging - the exception text maps 1:1 to its sending logs.","Run bin/mail send-test after key or domain changes."],"tags":["phabricator","metamta","mailgun","send-failure","api-error"],"backgroundTag":"email-send-rejected","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}