{"record":{"id":"5d4ddb9797d8dc7f","repo":"immich-app/immich","slug":"metadata-with-key-key-not-found-for-asset-wit","errorCode":null,"errorMessage":"Metadata with key \"${key}\" not found for asset with id \"${id}\"","messagePattern":"Metadata with key \"(.+?)\" not found for asset with id \"(.+?)\"","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/asset.service.ts","lineNumber":438,"sourceCode":"\n    const uniqueKeys = new Set<string>();\n    for (const { key } of dto.items) {\n      if (uniqueKeys.has(key)) {\n        throw new BadRequestException(`Duplicate items are not allowed: \"${key}\"`);\n      }\n\n      uniqueKeys.add(key);\n    }\n\n    return this.assetRepository.upsertMetadata(id, dto.items);\n  }\n\n  async getMetadataByKey(auth: AuthDto, id: string, key: string): Promise<AssetMetadataResponseDto> {\n    await this.requireAccess({ auth, permission: Permission.AssetRead, ids: [id] });\n\n    const item = await this.assetRepository.getMetadataByKey(id, key);\n    if (!item) {\n      throw new BadRequestException(`Metadata with key \"${key}\" not found for asset with id \"${id}\"`);\n    }\n    return item;\n  }\n\n  async deleteMetadataByKey(auth: AuthDto, id: string, key: string): Promise<void> {\n    await this.requireAccess({ auth, permission: Permission.AssetUpdate, ids: [id] });\n    return this.assetRepository.deleteMetadataByKey(id, key);\n  }\n\n  async deleteBulkMetadata(auth: AuthDto, dto: AssetMetadataBulkDeleteDto) {\n    await this.requireAccess({ auth, permission: Permission.AssetUpdate, ids: dto.items.map((item) => item.assetId) });\n    await this.assetRepository.deleteBulkMetadata(dto.items);\n  }\n\n  async run(auth: AuthDto, dto: AssetJobsDto) {\n    await this.requireAccess({ auth, permission: Permission.AssetUpdate, ids: dto.assetIds });\n\n    const jobs: JobItem[] = [];","sourceCodeStart":420,"sourceCodeEnd":456,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/asset.service.ts#L420-L456","documentation":"getMetadataByKey looked up a single metadata item by asset id and key, and the repository returned nothing. The service throws BadRequestException naming both the missing key and asset id. The key simply does not exist on that asset.","triggerScenarios":"GET /api/assets/:id/metadata/key/:key where no row in asset_metadata matches (assetId, key) — the key was never set, was deleted, or is misspelled.","commonSituations":"Requesting keys like 'face-1' that only exist when ML face detection has run; typos or casing differences in the key; assets processed before a metadata feature was enabled; key removed by a later edit.","solutions":["List all metadata for the asset (GET /api/assets/:id/metadata) to confirm the exact key name","Check key spelling and casing — keys are matched exactly","Handle 400 gracefully and return null/default when the key is optional","If the key should exist, run the relevant job (e.g. facial recognition, metadata extraction) for the asset first"],"exampleFix":"// before\nconst item = await api.getMetadataByKey(id, 'Face-1');\n// after\nconst all = await api.getAssetMetadata(id);\nconst item = all.find((m) => m.key === 'face-1') ?? null;","handlingStrategy":"fallback","validationCode":"const all = await api.getAssetMetadata(id);\nif (!all.some((m) => m.key === key)) return null; // key absent, skip lookup","typeGuard":null,"tryCatchPattern":"try { return await api.getMetadataByKey(id, key); } catch (e) { if (String(e?.response?.data?.message).includes('not found')) return null; throw e; }","preventionTips":["Confirm exact key names via the asset's metadata list endpoint","Match keys case-sensitively and store them as constants","Treat optional metadata keys as nullable in client models","Run the ML/metadata job before expecting derived keys to exist"],"tags":["metadata","not-found","key","rest-api"],"backgroundTag":"record-not-found","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"}