immich-app/immich · warning · BadRequestException

Only images can be edited

Error message

Only images can be edited

What it means

Thrown by editAsset when the resolved asset's type is not AssetType.Image (e.g. video, audio, or other). The editor only supports raster images, so any other type is rejected with 400 BadRequest before any edit is applied. This is a hard capability gate, independent of file extension.

Source

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

    await this.requireAccess({ auth, permission: Permission.AssetRead, ids: [id] });
    const edits = await this.assetEditRepository.getAll(id);

    return {
      assetId: id,
      edits,
    };
  }

  async editAsset(auth: AuthDto, id: string, dto: AssetEditsCreateDto): Promise<AssetEditsResponseDto> {
    await this.requireAccess({ auth, permission: Permission.AssetEditCreate, ids: [id] });

    const asset = await this.assetRepository.getForEdit(id);
    if (!asset) {
      throw new BadRequestException('Asset not found');
    }

    if (asset.type !== AssetType.Image) {
      throw new BadRequestException('Only images can be edited');
    }

    if (asset.livePhotoVideoId) {
      throw new BadRequestException('Editing live photos is not supported');
    }

    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');
    }

View on GitHub (pinned to 199723261c)

Solutions

  1. Gate the edit button in the UI on asset.type === 'IMAGE'.
  2. Filter the selectable collection to images only before entering the editor.
  3. If you must process a video frame, extract a still image asset first and edit that.

Example fix

// before
if (asset) openEditor(asset);

// after
if (asset && asset.type === 'IMAGE' && !asset.livePhotoVideoId) {
  openEditor(asset);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const isEditableImage = (a): a is ImageAsset =>
  a?.type === 'IMAGE' && !a.livePhotoVideoId;
if (!isEditableImage(asset)) {
  throw new Error('Only still images can be edited.');
}

Type guard

function isEditableImage(asset: unknown): asset is { type: 'IMAGE'; id: string } {
  return !!asset && typeof asset === 'object' && (asset as any).type === 'IMAGE';
}

Prevention

When it happens

Trigger: PUT /assets/{id}/edits on a video, audio file, or any asset whose type !== 'IMAGE'; attempting to route a motion/video asset through the image editor.

Common situations: UI lists all assets in one grid and lets the user open the editor on a video; client does not filter by type before enabling the edit action; a live-photo still paired with a video where the wrong record is targeted.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/0b9273745bb0a97e. Report an issue: GitHub.