immich-app/immich · warning · BadRequestException
Partner not found
Error message
Partner not found
What it means
Thrown by PartnerService.remove when partnerRepository.get(partnerId) returns null. The caller is attempting to unshare from a user they never shared with. BadRequestException -> HTTP 400.
Source
Thrown at server/src/services/partner.service.ts:33
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);
const key = direction === PartnerDirection.SharedBy ? 'sharedById' : 'sharedWithId';
return partners
.filter((partner): partner is Partner => !!(partner.sharedBy && partner.sharedWith)) // Filter out soft deleted users
.filter((partner) => partner[key] === auth.user.id)
.map((partner) => this.mapPartner(partner, direction));
}
async update(auth: AuthDto, sharedById: string, dto: PartnerUpdateDto): Promise<PartnerResponseDto> {
await this.requireAccess({ auth, permission: Permission.PartnerUpdate, ids: [sharedById] });
const partnerId: PartnerIds = { sharedById, sharedWithId: auth.user.id };
View on GitHub (pinned to 199723261c)
Solutions
- Refresh the partner list before issuing the delete.
- Treat 400 'Partner not found' as already-removed success in idempotent delete flows.
- Guard the UI so users can only remove partners present in the current list.
Example fix
// before
const partner = await this.partnerRepository.get(partnerId);
if (!partner) {
throw new BadRequestException('Partner not found');
}
// after (DELETE is idempotent)
const partner = await this.partnerRepository.get(partnerId);
if (!partner) {
return;
} Defensive patterns
Strategy: validation
Validate before calling
// Confirm the partnership exists before issuing DELETE.
const partners = await partnerService.search(auth, { direction: 'shared-by' });
if (!partners.some((p) => p.id === sharedWithId)) return; // nothing to remove Type guard
const isPartner = (p: PartnerResponseDto | null | undefined): p is PartnerResponseDto => !!p && typeof p.id === 'string';
Try / catch
try {
await partnerService.remove(auth, sharedWithId);
} catch (e) {
if (e instanceof BadRequestException && /not found/i.test(e.message)) {
// already removed: idempotent success
return;
}
throw e;
} Prevention
- Treat remove as idempotent; swallow 'Partner not found' as success.
- Refresh the partner list before issuing delete.
- Lock the UI row while the delete is in flight to prevent double-submits.
When it happens
Trigger: DELETE /partner/{sharedWithId} for a sharedWithId that is not currently a partner of the caller; double-delete after the share was already removed.
Common situations: UI state out of sync with server (a partner was removed elsewhere); client retries a delete that already succeeded; user removed from a stale list view.
Related errors
- Partner already exists
- Invalid user
- Can't delete a missing profile Image
- Unsupported file type ${filename}
- May not request original file
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/f58741da3db9bb45.
Report an issue: GitHub.