immich-app/immich · error · UnauthorizedException
Password required
Error message
Password required
What it means
SharedLink.getMine returns the caller's own shared link but enforces that the request's auth token matches the token derived from the link's password. If the link has a password and the presented auth token is not the expected password token, access is refused with UnauthorizedException('Password required').
Solutions
- Complete the shared-link password login first, then use the returned token for getMine.
- If the link password changed, re-authenticate with the new password to mint a fresh token.
- For passwordless links no token exchange is needed — verify the right link/key is used.
Example fix
// before
const link = await api.getMySharedLink(shareKeyToken); // token predates password
// after
const { token } = await api.sharedLinkLogin(shareKey, { password });
const link = await api.getMySharedLink(token); Defensive patterns
Strategy: try-catch
Try / catch
try {
return await api.getMySharedLink(token);
} catch (e) {
if (e.status === 401 && e.message === 'Password required') {
const { token: fresh } = await api.sharedLinkLogin(shareKey, { password });
return await api.getMySharedLink(fresh);
}
throw e;
} Prevention
- Always run the password login exchange before getMine for protected links.
- Discard cached tokens after the link password changes.
- Store the token returned by login, not the raw share key.
When it happens
Trigger: GET /shared-links/me (getMine) authenticated with auth.sharedLink credentials whose token is not in authTokens for a password-protected link — e.g. accessing the link metadata without first completing the password login.
Common situations: Client fetches /me directly with the share key without exchanging the password for a token; owner changed the link password so the cached token no longer matches.
Related errors
- Invalid password
- Invalid API key
- Invalid JWT Token
- Missing JWT Token
- Shared link is not password protected
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/cd4a8c2a38e3b999.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/shared-link.service.ts:58
throw new UnauthorizedException('Invalid password');
}
return {
sharedLink: mapSharedLink(sharedLink, { stripAssetMetadata: !sharedLink.showExif }),
token: this.asToken({ id, password }),
};
}
async getMine(auth: AuthDto, authTokens: string[]) {
if (!auth.sharedLink) {
throw new ForbiddenException();
}
const sharedLink = await this.findOrFail(auth.user.id, auth.sharedLink.id);
const { id, password } = sharedLink;
if (password && !authTokens.includes(this.asToken({ id, password }))) {
throw new UnauthorizedException('Password required');
}
return mapSharedLink(sharedLink, { stripAssetMetadata: !sharedLink.showExif });
}
async get(auth: AuthDto, id: string): Promise<SharedLinkResponseDto> {
const sharedLink = await this.findOrFail(auth.user.id, id);
return mapSharedLink(sharedLink, { stripAssetMetadata: false });
}
async create(auth: AuthDto, dto: SharedLinkCreateDto): Promise<SharedLinkResponseDto> {
switch (dto.type) {
case SharedLinkType.Album: {
if (!dto.albumId) {
throw new BadRequestException('Invalid albumId');
}
await this.requireAccess({ auth, permission: Permission.AlbumShare, ids: [dto.albumId] });
break;View on GitHub (pinned to e55ac299a4)