immich-app/immich · error · BadRequestException

Invalid user

Error message

Invalid user

What it means

Thrown by PartnerService.create when userRepository.get(sharedWithId, {}) returns null after the exists-check passed. Means the requested sharedWithId does not reference a real user. BadRequestException -> HTTP 400. Logged at debug level as 'Partner creation failed: user not found'.

Source

Thrown at server/src/services/partner.service.ts:22

import { PartnerCreateDto, PartnerResponseDto, PartnerSearchDto, PartnerUpdateDto } from 'src/dtos/partner.dto';
import { mapUser } from 'src/dtos/user.dto';
import { Permission } from 'src/enum';
import { PartnerDirection, PartnerIds } from 'src/repositories/partner.repository';
import { BaseService } from 'src/services/base.service';

@Injectable()
export class PartnerService extends BaseService {
  async create(auth: AuthDto, { sharedWithId }: PartnerCreateDto): Promise<PartnerResponseDto> {
    const partnerId: PartnerIds = { sharedById: auth.user.id, sharedWithId };
    const exists = await this.partnerRepository.get(partnerId);
    if (exists) {
      throw new BadRequestException(`Partner already exists`);
    }

    const user = await this.userRepository.get(sharedWithId, {});
    if (!user) {
      this.logger.debug('Partner creation failed: user not found');
      throw new BadRequestException('Invalid user');
    }

    const partner = await this.partnerRepository.create(partnerId);
    return this.mapPartner(partner, PartnerDirection.SharedBy);
  }

  async remove(auth: AuthDto, sharedWithId: string): Promise<void> {
    const partnerId: PartnerIds = { sharedById: auth.user.id, sharedWithId };
    const partner = await this.partnerRepository.get(partnerId);
    if (!partner) {
      throw new BadRequestException('Partner not found');
    }

    await this.partnerRepository.remove(partnerId);
  }

  async search(auth: AuthDto, { direction }: PartnerSearchDto): Promise<PartnerResponseDto[]> {
    const partners = await this.partnerRepository.getAll(auth.user.id);

View on GitHub (pinned to 199723261c)

Solutions

  1. Verify sharedWithId is a valid user id by calling GET /users (or the admin user list) before submitting.
  2. Refresh the user-picker data source if it may be stale.
  3. Handle 400 'Invalid user' in the UI by clearing the selection and re-fetching the user list.

Example fix

// before
const user = await this.userRepository.get(sharedWithId, {});
if (!user) {
  this.logger.debug('Partner creation failed: user not found');
  throw new BadRequestException('Invalid user');
}

// after (use 404 so the semantics match the resource)
const user = await this.userRepository.get(sharedWithId, {});
if (!user) {
  throw new NotFoundException(`User ${sharedWithId} not found`);
}
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the target user exists before submitting the create.
const users = await userService.getAll(auth, {}); // or GET /users
if (!users.find((u) => u.id === sharedWithId)) {
  throw new Error('Refusing to create partner: target user does not exist');
}

Type guard

const isValidUserId = (id: string): boolean =>
  /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id);

Try / catch

try {
  await partnerService.create(auth, { sharedWithId });
} catch (e) {
  if (e instanceof BadRequestException && e.message === 'Invalid user') {
    // refresh the user list, clear the stale selection
  }
  throw e;
}

Prevention

When it happens

Trigger: POST /partner with a sharedWithId that is not a registered user, has been hard-deleted, or is a malformed UUID.

Common situations: Client passes the wrong user id (e.g. an album id or a device id); the target user was deleted between the UI loading a suggestion list and the create call; a stale cache of user ids.

Related errors


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