{"record":{"id":"64f66f0975205ad6","repo":"phacility/phabricator","slug":"failed-to-json-decode-response","errorCode":null,"errorMessage":"Failed to JSON decode response.","messagePattern":"Failed to JSON decode response\\.","errorType":"exception","errorClass":"PhutilProxyException","httpStatus":null,"severity":"error","filePath":"src/applications/metamta/adapter/PhabricatorMailMailgunAdapter.php","lineNumber":122,"sourceCode":"      ->setHTTPBasicAuthCredentials('api', new PhutilOpaqueEnvelope($api_key))\n      ->setTimeout(60);\n\n    $attachments = $message->getAttachments();\n    foreach ($attachments as $attachment) {\n      $future->attachFileData(\n        'attachment',\n        $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":104,"sourceCodeEnd":137,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/metamta/adapter/PhabricatorMailMailgunAdapter.php#L104-L137","documentation":"After POSTing a message to Mailgun's API, PhabricatorMailMailgunAdapter resolves the HTTP future and decodes the body with phutil_json_decode(). The body failed to parse, so the adapter wraps the PhutilJSONParserException in a PhutilProxyException with this message - meaning Mailgun (or something between Phabricator and Mailgun, such as a proxy or captive portal) returned HTML, an empty body, or truncated output instead of JSON.","triggerScenarios":"Sending mail through the mailgun adapter (mail workers, 'bin/mail send-test') while an intercepting egress proxy returns an HTML block page for api.mailgun.net; Mailgun itself returning a non-JSON error page (5xx, rate-limit page); a wrong 'domain' option resolving to a host that answers with HTML; truncated responses from network middleware.","commonSituations":"Egress-filtered corporate/server environments where api.mailgun.net is not directly reachable; SSL/TLS inspection rewriting responses; a typo'd domain option; transient Mailgun incidents. Because this is a plain Exception, the PhabricatorMetaMTAWorker treats the send as a temporary failure and retries it.","solutions":["Read the chained exception: the PhutilJSONParserException message contains the actual bytes that failed to parse - find it in the daemon log or the mail's delivery error - and identify whether it is a proxy page, an HTML error, or an empty body.","Verify direct egress from the host: curl -sS https://api.mailgun.net/v3/<your-domain>/messages from the machine running the daemons.","Check the mailer's 'domain' and 'api-key' options ('bin/config get cluster.mailers') - a wrong domain commonly produces non-JSON 404 pages.","If a proxy is mandatory, exempt api.mailgun.net from interception, or switch that mailer to type 'smtp' and let Mailgun's SMTP relay handle delivery."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  $adapter->sendMessage($message);\n} catch (PhutilProxyException $ex) {\n  if (preg_match('/Failed to JSON decode response/', $ex->getMessage())) {\n    // Transport/proxy interference: log $ex->getPrevious() (contains the raw\n    // body) and retry with backoff; alert if failures persist.\n    return retry_later($message);\n  }\n  throw $ex;\n}","preventionTips":["Whitelist mail API hosts (api.mailgun.net) on egress firewalls and exempt them from TLS inspection.","Smoke-test the mailer with 'bin/mail send-test' after any network or config change.","Monitor the mail queue failure rate - a spike of JSON-decode failures indicates proxy/egress problems, not bad mail."],"tags":["phabricator","metamta","mailgun","json","api-response","proxy","network"],"backgroundTag":"malformed-api-response","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}