immich-app/immich · error · UnauthorizedException
Invalid share slug
Error message
Invalid share slug
What it means
Shared links can be addressed by a human-readable slug instead of a key. The service resolves the slug via sharedLinkRepository.getBySlug and applies the same validity check (exists, not expired). Failure yields UnauthorizedException.
Solutions
- Verify the exact slug with the owner and retry
- Regenerate the share link and use the new slug
- Ask the owner to extend the expiry
- Check whether the share was deleted or the album removed
Defensive patterns
Strategy: try-catch
Try / catch
catch (e) { if (e.status === 401 && e.message === 'Invalid share slug') { /* prompt for fresh link */ } } Prevention
- Bookmark links via the app, not hand-typed slugs
- Monitor link expiry
- Confirm slugs after renames
When it happens
Trigger: GET /share/<slug> where the slug does not match any existing share link, or the matching link has expired or been revoked.
Common situations: Typos in the slug; slug reused/renamed by the owner; share deleted after album/asset was unshared; expired link still bookmarked.
Related errors
AI-assisted analysis of immich-app/immich@f48d4b3321 (2026-09-15).
Data as JSON: /api/errors/3334301cb923d4df.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/auth.service.ts:515
async validateSharedLinkKey(key: string | string[]): Promise<AuthDto> {
key = Array.isArray(key) ? key[0] : key;
const bytes = Buffer.from(key, key.length === 100 ? 'hex' : 'base64url');
const sharedLink = await this.sharedLinkRepository.getByKey(bytes);
if (!this.isValidSharedLink(sharedLink)) {
throw new UnauthorizedException('Invalid share key');
}
return { user: sharedLink.user, sharedLink };
}
async validateSharedLinkSlug(slug: string | string[]): Promise<AuthDto> {
slug = Array.isArray(slug) ? slug[0] : slug;
const sharedLink = await this.sharedLinkRepository.getBySlug(slug);
if (!this.isValidSharedLink(sharedLink)) {
throw new UnauthorizedException('Invalid share slug');
}
return { user: sharedLink.user, sharedLink };
}
private isValidSharedLink(
sharedLink?: AuthSharedLink & { user: AuthUser | null },
): sharedLink is AuthSharedLink & { user: AuthUser } {
return !!sharedLink?.user && (!sharedLink.expiresAt || new Date(sharedLink.expiresAt) > new Date());
}
private async validateApiKey(key: string): Promise<AuthDto> {
const hashed = this.cryptoRepository.hashSha256(key);
const apiKey = await this.apiKeyRepository.getKey(hashed);
if (apiKey?.user) {
return {
user: apiKey.user,
apiKey,View on GitHub (pinned to f48d4b3321)