phacility/phabricator · error · Exception
Expected '%s' in response!
Error message
Expected '%s' in response!
What it means
readTokenAndTokenSecret() parses every OAuth 1 token response (both the request-token step and the access-token step in finishOAuthHandshake()) and requires an oauth_token entry. If idx($data, 'oauth_token') is empty, the provider returned a 200 body that does not contain a token - typically an error payload, an HTML page, or a differently-formatted response that parseQueryString() could not map.
Source
Thrown at src/applications/auth/adapter/PhutilOAuth1AuthAdapter.php:188
}
$validate_uri = $this->getValidateTokenURI();
$params = array(
'oauth_verifier' => $this->getVerifier(),
);
list($body) = $this->newOAuth1Future($validate_uri, $params)->resolvex();
$data = id(new PhutilQueryStringParser())->parseQueryString($body);
$this->readTokenAndTokenSecret($data);
$this->handshakeData = $data;
}
private function readTokenAndTokenSecret(array $data) {
$token = idx($data, 'oauth_token');
if (!$token) {
throw new Exception(pht("Expected '%s' in response!", 'oauth_token'));
}
$token_secret = idx($data, 'oauth_token_secret');
if (!$token_secret) {
throw new Exception(
pht("Expected '%s' in response!", 'oauth_token_secret'));
}
$this->setToken($token);
$this->setTokenSecret($token_secret);
return $this;
}
/**
* Hook that allows subclasses to take actions before the OAuth handshake
* is completed.
*/View on GitHub (pinned to 5720a38cfe)
Solutions
- Log or inspect the raw response body ($body before parseQueryString) to see the provider's actual error message.
- Verify the consumer key and consumer secret configured for the adapter.
- Check getRequestTokenURI()/getValidateTokenURI() values against the provider's current documentation.
- Confirm the adapter's signature method and timestamp handling match what the provider expects.
Example fix
// before: the provider's error body is discarded and the exception is opaque
list($body) = $this->newOAuth1Future($validate_uri, $params)->resolvex();
$data = id(new PhutilQueryStringParser())->parseQueryString($body);
// after: surface the raw body when required parameters are missing
list($body) = $this->newOAuth1Future($validate_uri, $params)->resolvex();
$data = id(new PhutilQueryStringParser())->parseQueryString($body);
if (empty($data['oauth_token'])) {
throw new Exception(pht('Provider token response was: %s', $body));
} Defensive patterns
Strategy: try-catch
Try / catch
try {
$adapter->finishOAuthHandshake();
} catch (Exception $ex) {
phlog(sprintf(
'OAuth1 token exchange failed for provider "%s": %s',
$provider_key,
$ex->getMessage()));
return $this->newDialog()
->setTitle(pht('Authentication Failed'))
->appendParagraph($ex->getMessage());
} Prevention
- Capture and log the raw provider body when building custom adapters so failures are diagnosable.
- Validate consumer key/secret against the provider's app console before enabling the provider.
- Monitor provider API changelogs for endpoint or response-format changes.
When it happens
Trigger: The validate-token or request-token endpoint returns 200 with an error body (e.g. 'oauth_problem=...') instead of a token; the body is HTML or JSON, so query-string parsing yields no oauth_token; the consumer key/secret are wrong and the provider signals the error in the body rather than the HTTP status; the response format changed after a provider API upgrade.
Common situations: Bad consumer key or secret on a provider that returns 200 for signature failures; provider endpoint returning JSON instead of a query string; clock skew or signature method mismatch producing provider error pages; the provider renaming endpoints after a version bump.
Related errors
- Expected '%s' to be '%s'!
- Expected token to finish OAuth handshake!
- Expected verifier to finish OAuth handshake!
- Failed to decode OAuth access token response: %s
- Access token error: %s
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/4239c867268234ff.
Report an issue: GitHub.