{"record":{"id":"2011ac64359b2a84","repo":"immich-app/immich","slug":"asset-dimensions-are-not-available-for-editing","errorCode":null,"errorMessage":"Asset dimensions are not available for editing","messagePattern":"Asset dimensions are not available for editing","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"server/src/services/asset.service.ts","lineNumber":559,"sourceCode":"    }\n\n    if (isPanorama(asset)) {\n      throw new BadRequestException('Editing panorama images is not supported');\n    }\n\n    if (asset.originalPath?.toLowerCase().endsWith('.gif')) {\n      throw new BadRequestException('Editing GIF images is not supported');\n    }\n\n    if (asset.originalPath?.toLowerCase().endsWith('.svg')) {\n      throw new BadRequestException('Editing SVG images is not supported');\n    }\n\n    // check that crop parameters will not go out of bounds\n    const { width: assetWidth, height: assetHeight } = getDimensions(asset);\n\n    if (!assetWidth || !assetHeight) {\n      throw new BadRequestException('Asset dimensions are not available for editing');\n    }\n\n    const edits = dto.edits as AssetEditActionItem[];\n    const crop = edits.find((e) => e.action === AssetEditAction.Crop);\n    if (crop) {\n      if (edits[0].action !== AssetEditAction.Crop) {\n        throw new BadRequestException('Crop action must be the first edit action');\n      }\n\n      // check that crop parameters will not go out of bounds\n      const { width: assetWidth, height: assetHeight } = getDimensions(asset);\n\n      if (!assetWidth || !assetHeight) {\n        throw new BadRequestException('Asset dimensions are not available for editing');\n      }\n\n      const { x, y, width, height } = crop.parameters;\n      if (x + width > assetWidth || y + height > assetHeight) {","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/asset.service.ts#L541-L577","documentation":"Thrown by editAsset at the unconditional dimension gate (line 558-559). getDimensions(asset) derives width/height from the asset's exifImage/encoded data; if both are absent or zero, the editor cannot compute crop bounds or preserve aspect ratio, so it rejects ANY edit (rotate/mirror included) with 400 BadRequest. This check runs for every edit request, not only crops.","triggerScenarios":"PUT /assets/:id/edits on an asset whose width and height are not yet populated (metadata/video-metadata extraction not finished, or extraction failed and left nulls).","commonSituations":"Editing immediately after upload before the metadata job runs; assets whose EXIF has no dimensions and transcoding has not populated them; corrupted upload that never got probed.","solutions":["Wait for the asset's metadata job to finish (asset.exifInfo has width/height) before enabling edit.","In the UI, disable the editor until asset.exifInfo?.width and height are present.","Re-run metadata extraction for the asset if dimensions remain missing."],"exampleFix":"// before\nif (asset.type === 'IMAGE') openEditor(asset);\n\n// after\nconst hasDims = !!asset.exifInfo?.width && !!asset.exifInfo?.height;\nif (asset.type === 'IMAGE' && hasDims) openEditor(asset);\nelse notify('Asset is still being processed; try again shortly.');","handlingStrategy":"validation","validationCode":"// Require populated dimensions before allowing any edit.\nconst w = asset.exifInfo?.width ?? asset.width;\nconst h = asset.exifInfo?.height ?? asset.height;\nif (!w || !h) {\n  throw new Error('Asset dimensions not ready; wait for metadata extraction.');\n}\nawait api.put(`/assets/${asset.id}/edits`, { edits });","typeGuard":"function hasDimensions(a: any): boolean {\n  const w = a?.exifInfo?.width ?? a?.width;\n  const h = a?.exifInfo?.height ?? a?.height;\n  return Number.isFinite(w) && w > 0 && Number.isFinite(h) && h > 0;\n}","tryCatchPattern":null,"preventionTips":["Disable the editor until the metadata job populates width/height.","Poll or subscribe to asset updates so the UI enables editing once dimensions arrive.","Re-run metadata extraction for assets stuck without dimensions."],"tags":["asset","edit","dimensions","validation","metadata","image"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}