immich-app/immich · critical · InternalServerErrorException
Error in OAuth discovery: ${error}
Error message
Error in OAuth discovery: ${error} What it means
`getClient` performs OIDC discovery against the provider's well-known configuration using openid-client and wraps any failure in an InternalServerErrorException('Error in OAuth discovery: ...'). The original error (which may be an AggregateError from multiple discovery endpoints) is attached as `cause`. This means the server could not obtain/validate the provider's OIDC metadata.
Source
Thrown at server/src/repositories/oauth.repository.ts:223
try {
return await discovery(
new URL(issuerUrl),
clientId,
{
client_secret: clientSecret,
response_types: ['code'],
userinfo_signed_response_alg: profileSigningAlgorithm === 'none' ? undefined : profileSigningAlgorithm,
id_token_signed_response_alg: signingAlgorithm,
},
this.getTokenAuthMethod(tokenEndpointAuthMethod, clientSecret),
{
execute: allowInsecureRequests ? [allowInsecureRequestsExecute] : [],
timeout,
},
);
} catch (error: any | AggregateError) {
this.logger.error('Error in OAuth discovery', error);
throw new InternalServerErrorException(`Error in OAuth discovery: ${error}`, { cause: error });
}
}
private getTokenAuthMethod(tokenEndpointAuthMethod: OAuthTokenEndpointAuthMethod, clientSecret?: string) {
if (!clientSecret) {
return None();
}
switch (tokenEndpointAuthMethod) {
case OAuthTokenEndpointAuthMethod.ClientSecretPost: {
return ClientSecretPost(clientSecret);
}
case OAuthTokenEndpointAuthMethod.ClientSecretBasic: {
return ClientSecretBasic(clientSecret);
}
default: {View on GitHub (pinned to 5666d57f15)
Solutions
- Read `error.cause` (and server logs — the original error is logged) to see the underlying failure: DNS, TLS, or HTTP status.
- Open `<issuer>/.well-known/openid-configuration` from the server (curl inside the container) and verify it returns valid JSON with matching issuer.
- Fix the issuer URL in OAuth settings — it must exactly match the `issuer` claim in the discovery document.
- For self-signed/internal CAs, install the CA cert in the server's trust store or set NODE_EXTRA_CA_CERTS.
- For plain-HTTP internal providers, enable insecure request allowance (allowInsecureRequests) — only on trusted internal networks.
Example fix
// before issuerUrl: 'https://keycloak:8080/realms/myrealm' // server can't reach 'keycloak' // after issuerUrl: 'https://keycloak.internal:8080/realms/myrealm' // resolvable from server // or curl from inside the container first to verify discovery JSON
Defensive patterns
Strategy: validation
Validate before calling
// verify discovery before configuring/using the client
const res = await fetch(`${issuerUrl}/.well-known/openid-configuration`);
if (!res.ok) throw new Error(`discovery HTTP ${res.status}`);
const doc = await res.json();
if (doc.issuer !== issuerUrl) throw new Error('issuer mismatch'); Type guard
function isInternalServerError(e: unknown): e is { status: number; response: string } {
return typeof e === 'object' && e !== null && 'status' in e && (e as any).status === 500;
} Try / catch
try {
const client = await getClient(issuerUrl, clientId, clientSecret);
} catch (e) {
// cause holds the original discovery error (may be AggregateError)
console.error('discovery failed:', (e as any).cause ?? e);
throw new ServiceUnavailable('OAuth provider unreachable');
} Prevention
- Curl the well-known endpoint from inside the server/container before saving OAuth settings.
- Make the issuer URL match the discovery document's issuer claim exactly (scheme, host, port, path).
- Trust internal/self-signed CAs properly (trust store or NODE_EXTRA_CA_CERTS) instead of disabling TLS.
- Only enable insecure HTTP discovery on trusted internal networks.
- Check Docker networking: container hostnames must resolve from the ML/API container, not just the host.
When it happens
Trigger: The issuer URL is wrong or lacks a valid `/.well-known/openid-configuration`; the provider is unreachable from the server (DNS, firewall, Docker network); the provider uses plain HTTP while secure fetch is enforced (allowInsecureRequests not enabled); TLS certificate errors (self-signed certs); discovery document missing required fields (issuer mismatch, no supported algorithms).
Common situations: Misconfigured issuer URL in server settings (trailing path mistakes, http vs https); self-hosted Keycloak/Authentik not reachable from the server container; self-signed or internal CA certificates; provider behind mTLS or an auth-gated proxy.
Related errors
- OAuth login failed
- Failed to verify SMTP configuration
- Invalid SMTP configuration
- Password login has been disabled
- Received backchannel logout request but OAuth is not enabled
AI-assisted analysis of immich-app/immich@5666d57f15 (2026-09-01).
Data as JSON: /api/errors/043ae2c4392af2d8.
Report an issue: GitHub.