immich-app/immich · error · BadRequestException

Asset does not have valid dimensions

Error message

Asset does not have valid dimensions

What it means

Thrown by PersonService.createFace when the asset has edits but is missing width/height on the asset or exifImageWidth/exifImageHeight on exifInfo. These dimensions are required to scale the client-supplied face box from preview space back to the original image space. BadRequestException -> HTTP 400.

Source

Thrown at server/src/services/person.service.ts:632

    const [asset, person] = await Promise.all([
      this.assetRepository.getById(dto.assetId, { edits: true, exifInfo: true }),
      this.findOrFail(dto.personId),
    ]);

    if (!asset) {
      throw new NotFoundException('Asset not found');
    }

    const edits = asset.edits || [];

    let topLeft: Point = { x: dto.x, y: dto.y };
    let bottomRight: Point = { x: dto.x + dto.width, y: dto.y + dto.height };

    // the coordinates received from the client are based on the edited preview image
    // we need to convert them to the coordinate space of the original unedited image
    if (edits.length > 0) {
      if (!asset.width || !asset.height || !asset.exifInfo?.exifImageWidth || !asset.exifInfo?.exifImageHeight) {
        throw new BadRequestException('Asset does not have valid dimensions');
      }

      // convert from preview to full dimensions
      const scaleFactor = asset.width / dto.imageWidth;
      topLeft = { x: topLeft.x * scaleFactor, y: topLeft.y * scaleFactor };
      bottomRight = { x: bottomRight.x * scaleFactor, y: bottomRight.y * scaleFactor };

      const [invertedTopLeft, invertedBottomRight] = transformPoints(
        [topLeft, bottomRight],
        edits,
        { width: asset.width, height: asset.height },
        { inverse: true },
      ).points;

      // make sure topLeft is top-left and bottomRight is bottom-right
      topLeft = {
        x: Math.min(invertedTopLeft.x, invertedBottomRight.x),
        y: Math.min(invertedTopLeft.y, invertedBottomRight.y),

View on GitHub (pinned to 199723261c)

Solutions

  1. Re-run Metadata Extraction (Administration > Jobs) for the asset so dimensions are populated.
  2. Tag the face on the unedited version of the asset (no edits => no scaling required).
  3. If EXIF is irrecoverable, set width/height manually via the metadata API before tagging.

Example fix

// before
if (!asset.width || !asset.height || !asset.exifInfo?.exifImageWidth || !asset.exifInfo?.exifImageHeight) {
  throw new BadRequestException('Asset does not have valid dimensions');
}

// after (skip preview->original scaling only when dimensions are missing AND the box matches original space)
const canScale = asset.width && asset.height && asset.exifInfo?.exifImageWidth && asset.exifInfo?.exifImageHeight;
if (edits.length > 0 && !canScale) {
  throw new BadRequestException('Cannot map face box: asset dimensions missing. Re-run metadata extraction.');
}
Defensive patterns

Strategy: validation

Validate before calling

// Before face-tagging on an edited asset, confirm dimensions exist.
const asset = await assetService.getById(auth, dto.assetId);
if (asset.edits?.length && (!asset.width || !asset.height || !asset.exifInfo?.exifImageWidth || !asset.exifInfo?.exifImageHeight)) {
  // queue metadata re-extraction and abort
  throw new Error('Asset missing dimensions; queue metadata extraction first');
}

Type guard

const hasDimensionsForScale = (a: AssetResponseDto): boolean =>
  !!a.width && !!a.height && !!a.exifInfo?.exifImageWidth && !!a.exifInfo?.exifImageHeight;

Try / catch

try {
  await personService.createFace(auth, dto);
} catch (e) {
  if (e instanceof BadRequestException && /valid dimensions/i.test(e.message)) {
    // trigger metadata re-extraction, then retry once
    await jobRepository.queue({ name: JobName.MetadataExtraction, data: { id: dto.assetId } });
  }
  throw e;
}

Prevention

When it happens

Trigger: POST face-create for an asset that has been edited but whose metadata extraction never produced width/height or EXIF image dimensions (corrupted or stripped EXIF, metadata job that failed).

Common situations: Asset uploaded with stripped EXIF; metadata extraction job failed for that asset; a sidecar-less RAW file with no decoded dimensions; the asset was edited before dimension metadata was populated.

Related errors


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