immich-app/immich · error · BadRequestException
Invalid assetIds
Error message
Invalid assetIds
What it means
For SharedLinkType.Individual, SharedLink.create requires a non-empty assetIds array; without it the link would share nothing. An empty or missing array triggers BadRequestException('Invalid assetIds') before the per-asset share permission check.
Solutions
- Provide at least one asset id in assetIds for Individual links.
- Disable/validate the submit action when the asset selection is empty.
- Use type Album with an albumId if the intent is sharing a whole album.
Example fix
// before
await api.createSharedLink({ type: SharedLinkType.Individual, assetIds: [] });
// after
await api.createSharedLink({ type: SharedLinkType.Individual, assetIds: selectedAssetIds }); Defensive patterns
Strategy: validation
Validate before calling
if (dto.type === SharedLinkType.Individual && (!dto.assetIds || dto.assetIds.length === 0)) {
throw new Error('Individual shared links require at least one assetId');
} Type guard
const hasAssets = (dto) => Array.isArray(dto.assetIds) && dto.assetIds.length > 0 && dto.assetIds.every((id) => typeof id === 'string');
Try / catch
try {
await api.createSharedLink(dto);
} catch (e) {
if (e.status === 400 && e.message === 'Invalid assetIds') {
// prompt: select at least one asset
} else {
throw e;
}
} Prevention
- Disable the create button while the asset selection is empty.
- Preserve selection across UI navigation.
- Assert non-empty assetIds in client-side form validation.
When it happens
Trigger: POST /shared-links with dto.type = SharedLinkType.Individual and dto.assetIds undefined, null, or an empty array.
Common situations: User deselects all assets in the share dialog but proceeds; batch selection lost on page navigation; asset list filtered to zero items before building the payload.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Invalid albumId
- Either password or pinCode is required
- Asset dimensions are not available for editing
- assetIds, albumId, or userId is required
- At least two people are required for merging
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/af69042f5bcaed61.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/shared-link.service.ts:81
async get(auth: AuthDto, id: string): Promise<SharedLinkResponseDto> {
const sharedLink = await this.findOrFail(auth.user.id, id);
return mapSharedLink(sharedLink, { stripAssetMetadata: false });
}
async create(auth: AuthDto, dto: SharedLinkCreateDto): Promise<SharedLinkResponseDto> {
switch (dto.type) {
case SharedLinkType.Album: {
if (!dto.albumId) {
throw new BadRequestException('Invalid albumId');
}
await this.requireAccess({ auth, permission: Permission.AlbumShare, ids: [dto.albumId] });
break;
}
case SharedLinkType.Individual: {
if (!dto.assetIds || dto.assetIds.length === 0) {
throw new BadRequestException('Invalid assetIds');
}
await this.requireAccess({ auth, permission: Permission.AssetShare, ids: dto.assetIds });
break;
}
}
try {
const sharedLink = await this.sharedLinkRepository.create({
key: this.cryptoRepository.randomBytes(50),
userId: auth.user.id,
type: dto.type,
albumId: dto.albumId || null,
assetIds: dto.assetIds,
description: dto.description || null,
password: dto.password,
expiresAt: dto.expiresAt || null,View on GitHub (pinned to e55ac299a4)