immich-app/immich · error · BadRequestException
OAuth is not enabled
Error message
OAuth is not enabled
What it means
Thrown by authorize() when the OAuth configuration in server settings has enabled=false, fetched fresh with withCache:false. The OAuth login flow cannot start while the feature is disabled server-side.
Solutions
- Enable OAuth in admin settings (Administration > Settings > OAuth Authentication) with valid issuer/client ID/secret
- Hide the OAuth login option in clients when OAuth is intentionally off
- Clear stale cached config after changing settings
- Verify you are targeting the correct server URL
Example fix
// before const cfg = await getConfig(); if (cfg.oauth) startOAuth(); // after const cfg = await getConfig(); if (cfg.oauth?.enabled) startOAuth(); else usePasswordLogin();
Defensive patterns
Strategy: fallback
Validate before calling
const { oauth } = await api.getConfig(); if (!oauth || !oauth.enabled) usePasswordLogin(); Type guard
const oauthReady = (c: { oauth?: { enabled?: boolean } }) => c.oauth?.enabled === true; Try / catch
try { await api.startOAuth(dto) } catch (e) { if (e.status === 400 && /OAuth is not enabled/.test(e.message)) return passwordLogin(); throw e; } Prevention
- Gate OAuth UI on the server-reported enabled flag
- Keep client and server OAuth settings in sync
- Document OAuth setup in deployment configs
When it happens
Trigger: Starting an OAuth login while the admin setting OAuth Authentication is disabled (oauth.enabled false).
Common situations: Fresh install where OAuth was never enabled; admin toggled OAuth off; clients still show an OAuth button; pointing at the wrong server instance.
Related errors
- Password login has been disabled
- Real-time transcoding is not enabled
- Received backchannel logout request but OAuth is not enabled
- Cannot update configuration while IMMICH_CONFIG_FILE is in…
- Codec ' ' is unsupported
AI-assisted analysis of immich-app/immich@f48d4b3321 (2026-09-15).
Data as JSON: /api/errors/837a032591a3970c.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/auth.service.ts:278
return this.validateSession(session, headers);
}
if (apiKey) {
return this.validateApiKey(apiKey);
}
throw new UnauthorizedException('Authentication required');
}
getMobileRedirect(url: string) {
return `${MOBILE_REDIRECT}?${url.split('?', 2)[1] || ''}`;
}
async authorize(dto: OAuthConfigDto) {
const { oauth } = await this.getConfig({ withCache: false });
if (!oauth.enabled) {
throw new BadRequestException('OAuth is not enabled');
}
return await this.oauthRepository.authorize(
oauth,
this.resolveRedirectUri(oauth, dto.redirectUri),
dto.state,
dto.codeChallenge,
);
}
async callback(dto: OAuthCallbackDto, headers: IncomingHttpHeaders, loginDetails: LoginDetails) {
const { oauth } = await this.getConfig({ withCache: false });
if (!oauth.enabled) {
throw new BadRequestException('OAuth is not enabled');
}
const expectedState = dto.state ?? this.getCookieOauthState(headers);
if (!expectedState?.length) {View on GitHub (pinned to f48d4b3321)