immich-app/immich · info · NotFoundException
Not Found
Error message
Not Found
What it means
Thrown by ServerService.getLicense when systemMetadataRepository.get(SystemMetadataKey.License) returns null. The server has no license key stored in system metadata. NotFoundException with no message -> HTTP 404 'Not Found'. Used by the license check endpoint to signal 'no license configured'.
Source
Thrown at server/src/services/server.service.ts:182
return serverStats;
}
getSupportedMediaTypes(): ServerMediaTypesResponseDto {
return {
video: Object.keys(mimeTypes.video),
image: Object.keys(mimeTypes.image),
sidecar: Object.keys(mimeTypes.sidecar),
};
}
async deleteLicense(): Promise<void> {
await this.systemMetadataRepository.delete(SystemMetadataKey.License);
}
async getLicense(): Promise<LicenseResponseDto> {
const license = await this.systemMetadataRepository.get(SystemMetadataKey.License);
if (!license) {
throw new NotFoundException();
}
return license;
}
async setLicense(dto: LicenseKeyDto): Promise<LicenseResponseDto> {
if (!dto.licenseKey.startsWith('IMSV-')) {
throw new BadRequestException('Invalid license key');
}
const { licensePublicKey } = this.configRepository.getEnv();
const isLicenseValid = this.cryptoRepository.verifySha256(
dto.licenseKey,
dto.activationKey,
licensePublicKey.server,
);
if (!isLicenseValid) {
throw new BadRequestException('Invalid license key');
}
View on GitHub (pinned to 199723261c)
Solutions
- Activate a license via POST/PUT /server/license (setLicense) before querying it.
- Treat 404 from this endpoint as 'no license configured' (not an error) in the client.
- Add a message to the NotFoundException so clients can distinguish from a generic 404.
Example fix
// before
const license = await this.systemMetadataRepository.get(SystemMetadataKey.License);
if (!license) {
throw new NotFoundException();
}
// after
const license = await this.systemMetadataRepository.get(SystemMetadataKey.License);
if (!license) {
throw new NotFoundException('No license configured');
}
// client-side
try {
return await api.get('/server/license');
} catch (e) {
if (e.status === 404) return null; // no license set
throw e;
} Defensive patterns
Strategy: validation
Validate before calling
// Check whether a license is configured before reading it.
const license = await systemMetadataRepository.get(SystemMetadataKey.License).catch(() => null);
if (!license) {
// no license configured; prompt admin to activate one
return null;
}
return license; Type guard
const hasLicense = (l: LicenseResponseDto | null | undefined): l is LicenseResponseDto => !!l && typeof l.licenseKey === 'string';
Try / catch
try {
return await serverService.getLicense();
} catch (e) {
if (e instanceof NotFoundException) {
// no license configured yet; not an error
return null;
}
throw e;
} Prevention
- Treat 404 from the license endpoint as 'no license set', not as a failure.
- Add a message to the NotFoundException for client-friendly semantics.
- Check license status before showing licensed features in the UI.
When it happens
Trigger: GET /server/license (or the license-view endpoint) on a server that has never had a license set, or whose license was deleted via deleteLicense.
Common situations: Fresh install; admin cleared the license; license was set on a different instance; checking license status before activation.
Related errors
- Invalid license key
- API Key not found
- Asset media not found
- Asset not found or asset is not a video
- Asset not found
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/7a68d6140de627ee.
Report an issue: GitHub.