immich-app/immich · error · BadRequestException

Asset dimensions are not available for editing

Error message

Asset dimensions are not available for editing

What it means

editAsset validates that the asset has known width/height (from getDimensions) before applying edit actions. Immich throws this BadRequestException when the stored asset lacks dimension metadata, since crop/rotate/flip math cannot be performed on an image of unknown size. It is a client-facing 400, meaning the request itself is fine but the asset state is not editable.

Solutions

  1. Wait for/re-run metadata extraction for the asset so width/height are populated (queue the AssetMetadataExtraction job), then retry the edit.
  2. Check the asset's exifInfo via GET /api/assets/:id; if width/height are null, fix the source file or re-upload it.
  3. If assets are stuck after migration, run a metadata backfill (re-generate thumbnails / re-extract metadata in admin jobs).
  4. Guard client-side: only call the edit endpoint for assets with known dimensions.

Example fix

// client-side guard before editing
const asset = await api.getAsset(assetId);
if (!asset.exifInfo?.exifImageWidth || !asset.exifInfo?.exifImageHeight) {
  throw new Error('Asset has no dimensions yet; wait for metadata extraction');
}
await api.editAsset(assetId, { edits });
Defensive patterns

Strategy: validation

Validate before calling

const asset = await api.getAsset(assetId);
if (!asset.exifInfo?.exifImageWidth || !asset.exifInfo?.exifImageHeight) {
  throw new Error(`Asset ${assetId} has no dimensions; skip edit`);
}

Try / catch

try { await api.editAsset(assetId, { edits }); } catch (e) { if (e.status === 400) queueMetadataRetry(assetId); else throw e; }

Prevention

When it happens

Trigger: PUT /api/assets/:id (editAsset) when the resolved asset's `exifInfo`/dimensions are missing or zero — i.e. getDimensions(asset) returns width or height of 0/undefined. This happens before any edit action (crop or otherwise) is applied.

Common situations: Assets uploaded before metadata extraction completed or that failed extraction (e.g. unsupported video codec, sidecar-less videos, corrupted files); assets migrated from an older Immich version where dimensions were never backfilled; non-visual assets passed to the edit endpoint.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/2011ac64359b2a84. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/asset.service.ts:564

    }

    if (isPanorama(asset)) {
      throw new BadRequestException('Editing panorama images is not supported');
    }

    if (asset.originalPath?.toLowerCase().endsWith('.gif')) {
      throw new BadRequestException('Editing GIF images is not supported');
    }

    if (asset.originalPath?.toLowerCase().endsWith('.svg')) {
      throw new BadRequestException('Editing SVG images is not supported');
    }

    // check that crop parameters will not go out of bounds
    const { width: assetWidth, height: assetHeight } = getDimensions(asset);

    if (!assetWidth || !assetHeight) {
      throw new BadRequestException('Asset dimensions are not available for editing');
    }

    const edits = dto.edits as AssetEditActionItem[];
    const crop = edits.find((e) => e.action === AssetEditAction.Crop);
    if (crop) {
      if (edits[0].action !== AssetEditAction.Crop) {
        throw new BadRequestException('Crop action must be the first edit action');
      }

      // check that crop parameters will not go out of bounds
      const { width: assetWidth, height: assetHeight } = getDimensions(asset);

      if (!assetWidth || !assetHeight) {
        throw new BadRequestException('Asset dimensions are not available for editing');
      }

      const { x, y, width, height } = crop.parameters;
      if (x + width > assetWidth || y + height > assetHeight) {

View on GitHub (pinned to e55ac299a4)