thephpleague/oauth2-server · error · OAuthServerException
invalid_client
invalid_client
Error message
invalid_client
What it means
invalid_client: the client was found but its registered redirect URI is empty, or it is an array with a count other than exactly 1. The auth code grant requires exactly one usable redirect URI, and a CLIENT_AUTHENTICATION_FAILED event is emitted before throwing.
Solutions
- Fix the client's stored redirect URI to a single non-empty string
- If your entity supports multiple redirect URIs, return exactly one where this grant requires it, or return a single string
- Update your ClientRepository/entity mapping so the redirect_uri column is not empty/null
- Re-check client seeding/migration scripts for blank redirect_uri values
Example fix
// before (client entity) $this->redirectUri = []; // or '' // after $this->redirectUri = 'https://app.example.com/callback';
Defensive patterns
Strategy: type-guard
Validate before calling
// in your ClientRepository::getClientEntity()
$redirectUri = $clientRecord['redirect_uri'] ?? '';
if (!is_string($redirectUri) || $redirectUri === '') {
throw new \RuntimeException('Client must have exactly one registered redirect URI');
} Type guard
function hasUsableRedirectUri($redirectUri): bool {
if (is_array($redirectUri)) {
return count($redirectUri) === 1;
}
return is_string($redirectUri) && $redirectUri !== '';
} Try / catch
try {
$authRequest = $server->validateAuthorizationRequest($request);
} catch (OAuthServerException $e) {
if ($e->getErrorType() === 'invalid_client') {
// fix the client record: redirect URI empty or multi-value array
}
} Prevention
- Validate client records (non-empty, single redirect URI) at seed/migration time
- Listen for the CLIENT_AUTHENTICATION_FAILED event to log misconfigurations early
- Implement ClientEntityInterface getters defensively
When it happens
Trigger: validateAuthorizationRequest() reaches the branch where $client->getRedirectUri() === '' or is_array($client->getRedirectUri()) && count(...) !== 1 — i.e. the client entity returned by your ClientRepository has a blank or multi-value (non-single) redirect URI.
Common situations: Custom ClientRepository returning a client entity with redirectUri left as an empty string or an array of several URIs; misconfigured client record in the database; implementing ClientEntityInterface without normalizing the redirect URI.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
AI-assisted analysis of thephpleague/oauth2-server@9d2f6fc0a0 (2026-09-15).
Data as JSON: /api/errors/8ac5ef40fcfcdd84.
Report an issue: GitHub.
Appendix: source
Thrown at src/Grant/AuthCodeGrant.php:279
);
if ($clientId === null) {
throw OAuthServerException::invalidRequest('client_id');
}
$client = $this->getClientEntityOrFail($clientId, $request);
$redirectUri = $this->getQueryStringParameter('redirect_uri', $request);
if ($redirectUri !== null) {
$this->validateRedirectUri($redirectUri, $client, $request);
} elseif (
$client->getRedirectUri() === '' ||
(is_array($client->getRedirectUri()) && count($client->getRedirectUri()) !== 1)
) {
$this->getEmitter()->emit(new RequestEvent(RequestEvent::CLIENT_AUTHENTICATION_FAILED, $request));
throw OAuthServerException::invalidClient($request);
}
$stateParameter = $this->getQueryStringParameter('state', $request);
$scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request, $this->defaultScope),
$this->makeRedirectUri(
$redirectUri ?? $this->getClientRedirectUri($client),
$stateParameter !== null ? ['state' => $stateParameter] : []
)
);
$authorizationRequest = $this->createAuthorizationRequest();
$authorizationRequest->setGrantTypeId($this->getIdentifier());
$authorizationRequest->setClient($client);
$authorizationRequest->setRedirectUri($redirectUri);
if ($stateParameter !== null) {View on GitHub (pinned to 9d2f6fc0a0)