{"record":{"id":"b62498a80c340baa","repo":"immich-app/immich","slug":"invalid-license-key-b62498","errorCode":null,"errorMessage":"Invalid license key","messagePattern":"Invalid license key","errorType":"validation","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/user.service.ts","lineNumber":177,"sourceCode":"  async getLicense(auth: AuthDto): Promise<LicenseResponseDto> {\n    const metadata = await this.userRepository.getMetadata(auth.user.id);\n\n    const license = metadata.find(\n      (item): item is UserMetadataItem<UserMetadataKey.License> => item.key === UserMetadataKey.License,\n    );\n    if (!license) {\n      throw new NotFoundException();\n    }\n    return { ...license.value, activatedAt: new Date(license.value.activatedAt) };\n  }\n\n  async deleteLicense({ user }: AuthDto): Promise<void> {\n    await this.userRepository.deleteMetadata(user.id, UserMetadataKey.License);\n  }\n\n  async setLicense(auth: AuthDto, license: LicenseKeyDto): Promise<LicenseResponseDto> {\n    if (!license.licenseKey.startsWith('IMCL-') && !license.licenseKey.startsWith('IMSV-')) {\n      throw new BadRequestException('Invalid license key');\n    }\n\n    const { licensePublicKey } = this.configRepository.getEnv();\n\n    const isClientLicenseValid = this.cryptoRepository.verifySha256(\n      license.licenseKey,\n      license.activationKey,\n      licensePublicKey.client,\n    );\n\n    const isServerLicenseValid = this.cryptoRepository.verifySha256(\n      license.licenseKey,\n      license.activationKey,\n      licensePublicKey.server,\n    );\n\n    if (!isClientLicenseValid && !isServerLicenseValid) {\n      throw new BadRequestException('Invalid license key');","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/user.service.ts#L159-L195","documentation":"setLicense performs a quick prefix check on the license key before cryptographic verification: a valid key must start with 'IMCL-' (client) or 'IMSV-' (server). Keys with any other prefix are rejected immediately with a 400 Bad Request and never reach signature validation.","triggerScenarios":"POST /users/license with a licenseKey string that does not start with 'IMCL-' or 'IMSV-' — typos, truncated keys, license keys from a different product, or pasting only the activation key into the license key field.","commonSituations":"Copy/paste losing part of the key (missing prefix); confusing the license key with the activation key; purchasing/licensing flow mixing up Immich product editions; whitespace or BOM corrupting the prefix.","solutions":["Verify the license key starts exactly with 'IMCL-' or 'IMSV-' (no leading whitespace or missing characters).","Re-copy the full license key from the purchase email/account portal.","Ensure you are not pasting the activation key into the license key field (the two are separate inputs).","Confirm the key belongs to this Immich product edition; keys from unrelated products will have a different prefix."],"exampleFix":"// before\nawait api.setLicense({ licenseKey: 'XXXX-1234', activationKey: actKey });\n// after\nconst key = licenseInput.trim();\nif (!key.startsWith('IMCL-') && !key.startsWith('IMSV-')) {\n  throw new Error('license key must start with IMCL- or IMSV-');\n}\nawait api.setLicense({ licenseKey: key, activationKey: actKey });","handlingStrategy":"validation","validationCode":"const hasValidLicensePrefix = (key: string) => key.startsWith('IMCL-') || key.startsWith('IMSV-');\nif (!hasValidLicensePrefix(licenseKey.trim())) {\n  throw new Error('license key must start with IMCL- or IMSV-');\n}","typeGuard":"const isLicenseKey = (v: unknown): v is `IMCL-${string}` | `IMSV-${string}` =>\n  typeof v === 'string' && (v.startsWith('IMCL-') || v.startsWith('IMSV-'));","tryCatchPattern":"try {\n  await api.setLicense({ licenseKey, activationKey });\n} catch (e) {\n  if (e instanceof BadRequestException && e.message === 'Invalid license key') {\n    // show format/validity guidance to user\n  }\n}","preventionTips":["Trim whitespace/newlines from pasted keys.","Validate the IMCL-/IMSV- prefix client-side before submitting.","Keep license key and activation key fields distinct; never swap them.","Copy the full key from the source in one action to avoid truncation."],"tags":["license","validation","format","bad-request"],"backgroundTag":"invalid-argument-format","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}