immich-app/immich · warning · BadRequestException
OAuth is not enabled
Error message
OAuth is not enabled
What it means
BadRequestException (HTTP 400) thrown by AuthService.authorize when system config `oauth.enabled` is false. The authorize endpoint (POST /oauth/authorize) is the OAuth entry point; calling it without enabling OAuth in Administration > Settings returns this. Config is re-read without cache so a recent admin toggle is honored immediately.
Source
Thrown at server/src/services/auth.service.ts:274
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 199723261c)
Solutions
- As admin, enable OAuth in Administration > Settings > OAuth and configure the issuer/clientId.
- Reload the web app so it fetches the fresh server config and hides the OAuth button.
- Verify the config persisted by re-opening Settings after save.
- If using env overrides, confirm OAUTH_ENABLED is not forced off.
Example fix
// before
await axios.post('/oauth/authorize', { redirectUri: 'https://app/callback' });
// after
// admin enables OAuth in UI first, then:
await axios.post('/oauth/authorize', { redirectUri: 'https://app/callback' }); Defensive patterns
Strategy: validation
Validate before calling
async function oauthEnabled(): Promise<boolean> {
const { data } = await axios.get('/server/features');
return data.config?.oauth?.enabled === true || data.oauth?.enabled === true;
} Type guard
function isOauthEnabled(features: { oauth?: { enabled?: boolean } }): boolean {
return features.oauth?.enabled === true;
} Try / catch
try {
await axios.post('/oauth/authorize', { redirectUri });
} catch (e) {
if (e.response?.data?.message === 'OAuth is not enabled') {
hideOauthButton();
} else throw e;
} Prevention
- Drive the OAuth button visibility from a fresh server features fetch.
- Refresh server config after admin settings changes.
- Surface a clear 'OAuth disabled' message in the UI instead of a generic error.
When it happens
Trigger: POST /oauth/authorize with body {redirectUri} before an admin has toggled OAuth enabled in server settings. The web login screen may show an OAuth button based on stale client config while the server has it disabled.
Common situations: Admin disabled OAuth after the web app cached the enabled state; OAuth config import/migration reset the flag; multi-instance deployment where the user hits a node with a different config.
Related errors
- OAuth state is missing
- OAuth code verifier is missing
- OAuth authentication failed
- OAuth profile does not have an email address
- This OAuth account has already been linked to another user.
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/837a032591a3970c.
Report an issue: GitHub.