{"record":{"id":"5f319721cbe474d7","repo":"phacility/phabricator","slug":"expected-valid-json-response-from-user-whoami-re","errorCode":null,"errorMessage":"Expected valid JSON response from \"user.whoami\" request.","messagePattern":"Expected valid JSON response from \"user\\.whoami\" request\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/auth/adapter/PhutilPhabricatorAuthAdapter.php","lineNumber":90,"sourceCode":"    );\n  }\n\n  public function getExtraTokenParameters() {\n    return array(\n      'grant_type' => 'authorization_code',\n    );\n  }\n\n  protected function loadOAuthAccountData() {\n    $uri = id(new PhutilURI($this->getPhabricatorURI('api/user.whoami')))\n      ->replaceQueryParam('access_token', $this->getAccessToken());\n    list($body) = id(new HTTPSFuture($uri))->resolvex();\n\n    try {\n      $data = phutil_json_decode($body);\n      return $data['result'];\n    } catch (PhutilJSONParserException $ex) {\n      throw new Exception(\n        pht(\n          'Expected valid JSON response from \"user.whoami\" request.'),\n        $ex);\n    }\n  }\n\n  private function getPhabricatorURI($path) {\n    return rtrim($this->phabricatorBaseURI, '/').'/'.ltrim($path, '/');\n  }\n\n}\n","sourceCodeStart":72,"sourceCodeEnd":102,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/auth/adapter/PhutilPhabricatorAuthAdapter.php#L72-L102","documentation":"The Phabricator auth adapter lets users log in using another Phabricator install: after OAuth 2 it fetches {base_uri}/api/user.whoami?access_token=... and expects a JSON Conduit response whose 'result' key holds the account data. phutil_json_decode() throwing PhutilJSONParserException means the body was not valid JSON, and it is re-thrown with the original parser exception attached as the cause.","triggerScenarios":"setPhabricatorURI() pointing at the wrong vhost, a subpath, or a wiki that returns HTML for /api/user.whoami; the remote install behind a proxy/SSO that answers with an HTML login or error page; a truncated response; the remote Phabricator too old or misconfigured so the endpoint does not exist; a stale cached DNS entry serving a parking page.","commonSituations":"Base URI configured with a trailing path component that breaks API routing; reverse proxy requiring authentication before the API; remote install upgraded/moved and the old URI now serves HTML; firewall appliances injecting block pages; typo in the domain serving a registrar's parking page.","solutions":["Verify the configured Phabricator base URI is the canonical install root (e.g., https://phab.example.com/, not a subpath or alternate vhost).","Manually test: curl 'https://phab.example.com/api/user.whoami?access_token=...' and confirm it returns JSON.","Confirm the access token is a valid Conduit token for the remote install (test it with 'arc' or a Conduit call).","Check for proxies, SSO walls, or SSL interception between the two installs that return HTML before the request reaches Phabricator."],"exampleFix":"// before: base URI includes a path that breaks Conduit routing\n$adapter->setPhabricatorURI('https://corp.example.com/phabricator/');\n\n// after: use the canonical install root, then verify externally\n$adapter->setPhabricatorURI('https://phab.corp.example.com/');\n// curl 'https://phab.corp.example.com/api/user.whoami?access_token=API-...' must return JSON","handlingStrategy":"try-catch","validationCode":"// Verify the endpoint returns JSON before enabling the provider\n$uri = rtrim($base_uri, '/').'/api/user.whoami?access_token='.$token;\nlist($body) = id(new HTTPSFuture($uri))->resolvex();\nif (phutil_json_decode($body) === null) {\n  throw new Exception('Base URI does not serve the Conduit API.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  $account_data = $adapter->getAccountData();\n} catch (Exception $ex) {\n  // The prior PhutilJSONParserException is chained as the cause.\n  phlog($ex);\n  return $this->newDialog()\n    ->setTitle(pht('Invalid Phabricator URI'))\n    ->appendParagraph(pht('Expected valid JSON response from \"user.whoami\".'));\n}","preventionTips":["Configure the Phabricator provider URI to the install root and curl the user.whoami endpoint during setup.","Verify the Conduit access token works (e.g., with arc) before wiring the provider.","Keep intermediate proxies from serving HTML on /api/ paths."],"tags":["oauth2","phabricator","conduit-api","response-parsing","php"],"backgroundTag":"api-invalid-response-format","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}