immich-app/immich · error · BadRequestException
This endpoint can only be used with a session token
Error message
This endpoint can only be used with a session token
What it means
unlockSession requires an authenticated session (cookie/bearer session), not just any auth context like an API key or shared link. If auth.session is undefined — e.g. the request authenticated via API key or another non-session mechanism — a BadRequestException is thrown.
Solutions
- Authenticate with a user login session (cookie or session bearer token) and retry
- Do not use x-api-key auth for session unlock endpoints
- Ensure the HTTP client forwards session cookies through proxies
Example fix
// before
await api.post('/session/unlock', dto, { headers: { 'x-api-key': key } });
// after
await api.post('/session/unlock', dto, { headers: { cookie: `immich_access_token=${sessionToken}` } }); Defensive patterns
Strategy: validation
Validate before calling
if (!auth.session) throw new Error('unlockSession requires a login session, not API-key auth'); Type guard
const hasSession = (a: AuthDto): a is AuthDto & { session: Session } => !!a.session; Try / catch
catch (e) { if (e.status === 400 && /session token/.test(e.message)) { /* re-authenticate with session */ } } Prevention
- Use session auth for session-management endpoints
- Forward cookies through proxies
- Never substitute API keys for session flows
When it happens
Trigger: Calling the session-unlock endpoint authenticated with an API key or shared-link auth instead of a user session token/cookie.
Common situations: Automation scripts using API keys calling unlockSession; shared-link auth accidentally routed to session endpoints; missing session cookie because cookies were not forwarded by a proxy or client.
Related errors
- This endpoint can only be used with a session token
- Unauthorized
- Wrong PIN code
- Authentication required
- authToken is required
AI-assisted analysis of immich-app/immich@f48d4b3321 (2026-09-15).
Data as JSON: /api/errors/2366b3c4ee4e77b9.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/auth.service.ts:594
});
}
}
return {
user: session.user,
session: {
id: session.id,
hasElevatedPermission,
},
};
}
throw new UnauthorizedException('Invalid user token');
}
async unlockSession(auth: AuthDto, dto: SessionUnlockDto): Promise<void> {
if (!auth.session) {
throw new BadRequestException('This endpoint can only be used with a session token');
}
const user = await this.userRepository.getForPinCode(auth.user.id);
this.validatePinCode(user, { pinCode: dto.pinCode });
await this.sessionRepository.update(auth.session.id, {
pinExpiresAt: DateTime.now().plus({ minutes: 15 }).toJSDate(),
});
}
async lockSession(auth: AuthDto): Promise<void> {
if (!auth.session) {
throw new BadRequestException('This endpoint can only be used with a session token');
}
await this.sessionRepository.update(auth.session.id, { pinExpiresAt: null });
}
View on GitHub (pinned to f48d4b3321)