immich-app/immich · warning · BadRequestException

Can't delete a missing profile Image

Error message

Can't delete a missing profile Image

What it means

deleteProfileImage is called when the authenticated user has no profile image set (profileImagePath is the empty string). Deleting a nonexistent profile image is treated as a client error, so a 400 Bad Request is thrown before any update or file-delete job runs.

Solutions

  1. Check the user's profileImagePath (GET /users/me) before calling delete; skip the call when it is empty.
  2. Treat the 400 with this message as an idempotent no-op in the client rather than surfacing it as an error.
  3. If the UI shows a photo but the server says none exists, refresh user state — the image was already deleted elsewhere.
  4. Guard delete buttons in the UI to be disabled when no profile photo is set.

Example fix

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

Strategy: validation

Validate before calling

const me = await api.getMyUser();
if (!me.profileImagePath) {
  return; // nothing to delete
}
await api.deleteProfileImage();

Try / catch

try {
  await api.deleteProfileImage();
} catch (e) {
  if (e instanceof BadRequestException && e.message.includes('missing profile Image')) {
    return; // already deleted — treat as no-op
  }
  throw e;
}

Prevention

When it happens

Trigger: DELETE /users/profile-image for a user whose profileImagePath === '' — i.e. the account never uploaded a profile photo, or it was already deleted (possibly by a concurrent request or the same client retrying).

Common situations: Client UI double-clicking the delete button; a stale client state showing a profile photo that was already removed in another tab/session; fresh accounts that never set a photo; scripts looping deletion over users.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: 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 e55ac299a4)