immich-app/immich · error · BadRequestException
Editing panorama images is not supported
Error message
Editing panorama images is not supported
What it means
editAsset blocks panorama images: isPanorama(asset) checks the asset's panorama classification (e.g. 360/Ricoh Theta files) and throws BadRequestException('Editing panorama images is not supported'). Crop/rotate transforms are meaningless or destructive for equirectangular panoramas, so they are rejected.
Solutions
- Detect panoramas before editing (isPanorama checks via the asset's flags/metadata — skip assets flagged as panorama)
- Filter 360-camera imports (e.g. Ricoh Theta) out of bulk edit operations
- Handle the 400 response and mark the asset as non-editable in the client UI
- Edit panoramas with dedicated 360 tooling instead of crop/rotate edits
Example fix
// before
await applyEdits(panoId, { crop: cropRect });
// after
if (asset.isPanorama) return skip('panorama');
await applyEdits(panoId, { crop: cropRect }); Defensive patterns
Strategy: validation
Validate before calling
if (asset.isPanorama) throw new Error(`Asset ${asset.id} is a panorama; editing not supported`); Type guard
const isPanorama = (a: { isPanorama?: boolean; tags?: string[] }) => a.isPanorama === true || !!a.tags?.includes('panorama'); Try / catch
try { await api.applyEdits(id, edits); } catch (e) { if (String(e?.response?.data?.message).includes('panorama')) { markNonEditable(id); return; } throw e; } Prevention
- Detect 360-camera files at import time and flag them
- Filter panoramas out of bulk edit batches
- Disable crop/rotate controls for equirectangular images
- Handle the 400 panorama response as a permanent skip
When it happens
Trigger: Submitting crop/rotate/flip edits for a 360-degree panorama asset (typically photos with GPS/EXIF panorama metadata from 360 cameras).
Common situations: Bulk edits over a library that includes Ricoh Theta / Insta360 / Google Street View panoramas; clients whose edit UI does not distinguish panoramas; scripts applying rotate to fix orientation across all images.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Editing live photos is not supported
- Editing GIF images is not supported
- Editing SVG images is not supported
- Only images can be edited
- Asset not found
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/e6bd553925d74cb9.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/asset.service.ts:549
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');
}
// 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[];View on GitHub (pinned to e55ac299a4)