immich-app/immich · error · BadRequestException

Storage label already in use by another account

Error message

Storage label already in use by another account

What it means

Thrown (as BadRequestException) by UserAdminService.update when dto.storageLabel is provided and userRepository.getByStorageLabel returns another user. Storage labels map to a unique on-disk subfolder, so duplicates are rejected before persistence to prevent asset path collisions.

Source

Thrown at server/src/services/user-admin.service.ts:78

      throw new BadRequestException('Admin status can only be changed by another admin');
    }

    if (dto.quotaSizeInBytes && user.quotaSizeInBytes !== dto.quotaSizeInBytes) {
      await this.userRepository.syncUsage(id);
    }

    if (dto.email) {
      const duplicate = await this.userRepository.getByEmail(dto.email);
      if (duplicate && duplicate.id !== id) {
        this.logger.debug('Email already in use by another account');
        throw new BadRequestException('Email is not available');
      }
    }

    if (dto.storageLabel) {
      const duplicate = await this.userRepository.getByStorageLabel(dto.storageLabel);
      if (duplicate && duplicate.id !== id) {
        throw new BadRequestException('Storage label already in use by another account');
      }
    }

    if (dto.password) {
      dto.password = await this.cryptoRepository.hashBcrypt(dto.password, SALT_ROUNDS);
    }

    if (dto.pinCode) {
      dto.pinCode = await this.cryptoRepository.hashBcrypt(dto.pinCode, SALT_ROUNDS);
    }

    if (dto.storageLabel === '') {
      dto.storageLabel = null;
    }

    const updatedUser = await this.userRepository.update(id, { ...dto, updatedAt: new Date() });

    return mapUserAdmin(updatedUser);

View on GitHub (pinned to 199723261c)

Solutions

  1. Choose a storage label not currently in use (list users and their labels first).
  2. Clear the label on the conflicting user (set to '' ) before assigning it here.
  3. Leave storageLabel empty to let Immich use the user id as the folder.

Example fix

// before
await usersApi.update(id, { storageLabel: 'jane' }); // 'jane' taken
// after
await usersApi.update(otherId, { storageLabel: '' });
await usersApi.update(id, { storageLabel: 'jane' });
Defensive patterns

Strategy: validation

Validate before calling

const owner = await userRepository.getByStorageLabel(dto.storageLabel);
if (owner && owner.id !== id) { /* show 'label taken' error, do not PUT */ }

Try / catch

try { await usersApi.update(id, dto); }
catch (e) {
  if (e instanceof BadRequestException && /Storage label already in use/.test(e.message)) {
    // clear the label on the other user, or choose a new label
  }
}

Prevention

When it happens

Trigger: PUT /admin/users/:id with a storageLabel already assigned to a different account.

Common situations: Renaming a user and reusing their old label; consolidating two users under one label; clearing then re-assigning a label that was reused.

Related errors


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