immich-app/immich · warning · BadRequestException

Can't delete a missing profile Image

Error message

Can't delete a missing profile Image

What it means

A BadRequestException (HTTP 400) thrown by UserService.deleteProfileImage when the user's profileImagePath is already an empty string, meaning there is no profile image to remove. The guard prevents a pointless FileDelete job and signals the client that the state is already as requested.

Source

Thrown at server/src/services/user.service.ts:139

    const user = await this.userRepository.update(auth.user.id, {
      profileImagePath,
      profileChangedAt: new Date(),
    });

    const toDelete = [file.path, ...(oldPath ? [oldPath] : [])];
    await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: toDelete } });

    return {
      userId: user.id,
      profileImagePath: user.profileImagePath,
      profileChangedAt: user.profileChangedAt,
    };
  }

  async deleteProfileImage(auth: AuthDto): Promise<void> {
    const user = await this.findOrFail(auth.user.id, { withDeleted: false });
    if (user.profileImagePath === '') {
      throw new BadRequestException("Can't delete a missing profile Image");
    }
    await this.userRepository.update(auth.user.id, { profileImagePath: '', profileChangedAt: new Date() });
    await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: [user.profileImagePath] } });
  }

  async getProfileImage(id: string): Promise<ImmichFileResponse> {
    const user = await this.userRepository.get(id, {});
    if (!user || !user.profileImagePath) {
      this.logger.debug('User or profile image not found');
      throw new NotFoundException();
    }

    return new ImmichFileResponse({
      path: user.profileImagePath,
      contentType: mimeTypes.lookup(user.profileImagePath),
      cacheControl: CacheControl.None,
    });
  }

View on GitHub (pinned to 199723261c)

Solutions

  1. Disable the 'remove profile image' control in the UI when the user has no custom image.
  2. Treat the 400 as success idempotently on the client since the desired state (no image) already holds.
  3. Before calling, GET the user profile and only send the delete if profileImagePath is non-empty.

Example fix

// before
await api.deleteProfileImage(); // 400 when already empty

// after
const me = await api.getUserMe();
if (me.profileImagePath) {
  await api.deleteProfileImage();
}
Defensive patterns

Strategy: validation

Validate before calling

const me = await api.getUserMe();
if (!me.profileImagePath) {
  return { ok: true, skipped: true, reason: 'No profile image to delete' };
}

Type guard

const isMissingProfileImageError = (e: unknown): boolean =>
  typeof e === 'object' && e !== null && (e as any).status === 400 && (e as any).message === "Can't delete a missing profile Image";

Try / catch

try {
  await api.deleteProfileImage();
} catch (e) {
  if (isMissingProfileImageError(e)) {
    // already in desired state; treat as success
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: DELETE /users/profile-image called by a user who never set a profile image, or who already deleted it. The check is a strict equality against the empty string.

Common situations: UI shows a default avatar but still offers a delete action; a retry of a delete that already succeeded; double-click on the remove button before the UI updates.

Related errors


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