immich-app/immich · warning · BadRequestException
Asset ${dto.queryAssetId} has no embedding
Error message
Asset ${dto.queryAssetId} has no embedding What it means
Thrown by SearchService.searchSmart when dto.queryAssetId is set, the asset is readable, but searchRepository.getEmbedding(dto.queryAssetId) returns no row (or no embedding column). Means the asset has never been embedded by the CLIP job, so it cannot be used as a search-by-image anchor. BadRequestException -> HTTP 400.
Source
Thrown at server/src/services/search.service.ts:170
const userIds = this.getUserIdsToSearch(auth, dto.visibility);
let embedding;
if (dto.query) {
const key = machineLearning.clip.modelName + dto.query + dto.language;
embedding = this.embeddingCache.get(key);
if (!embedding) {
embedding = await this.machineLearningRepository.encodeText(dto.query, {
modelName: machineLearning.clip.modelName,
language: dto.language,
});
this.embeddingCache.set(key, embedding);
}
} else if (dto.queryAssetId) {
await this.requireAccess({ auth, permission: Permission.AssetRead, ids: [dto.queryAssetId] });
const getEmbeddingResponse = await this.searchRepository.getEmbedding(dto.queryAssetId);
const assetEmbedding = getEmbeddingResponse?.embedding;
if (!assetEmbedding) {
throw new BadRequestException(`Asset ${dto.queryAssetId} has no embedding`);
}
embedding = assetEmbedding;
} else {
throw new BadRequestException('Either `query` or `queryAssetId` must be set');
}
const page = dto.page ?? 1;
const size = dto.size || 100;
const { hasNextPage, items } = await this.searchRepository.searchSmart(
{ page, size },
{
...dto,
userIds: await userIds,
embedding,
visibility: dto.visibility ?? (auth.session?.hasElevatedPermission ? undefined : 'not-locked'),
},
);
return this.mapResponse(items, hasNextPage ? (page + 1).toString() : null, { auth });View on GitHub (pinned to 199723261c)
Solutions
- Wait for or trigger the SmartSearch queue (Administration > Jobs) to embed the asset.
- Check the asset has a successful metadata extraction first (CLIP depends on it).
- Fall back to a text query (dto.query) instead of queryAssetId until embeddings are built.
- Verify the immich-machine-learning service is healthy so future assets get embedded.
Example fix
// before
if (!assetEmbedding) {
throw new BadRequestException(`Asset ${dto.queryAssetId} has no embedding`);
}
// client-side guard
const embedding = await api.get(`/assets/${queryAssetId}/embedding`);
if (!embedding) {
showToast('This asset has no smart embedding yet. Run the Smart Search job.');
return;
} Defensive patterns
Strategy: validation
Validate before calling
// Confirm the asset has an embedding before using it as a query anchor.
const embedding = await searchRepository.getEmbedding(queryAssetId);
if (!embedding?.embedding) {
// queue SmartSearch for this asset and fall back to text query
throw new Error(`Asset ${queryAssetId} has no embedding yet`);
} Type guard
const hasEmbedding = (e: { embedding?: string } | null | undefined): e is { embedding: string } =>
!!e && typeof e.embedding === 'string' && e.embedding.length > 0; Try / catch
try {
await searchService.searchSmart(auth, dto);
} catch (e) {
if (e instanceof BadRequestException && /no embedding/i.test(e.message)) {
// fall back to a text query
return searchService.searchSmart(auth, { ...dto, query: fallbackText, queryAssetId: undefined });
}
throw e;
} Prevention
- Run the SmartSearch queue before exposing search-by-image.
- Fall back to text query when the anchor asset lacks an embedding.
- Monitor ML job failures so embeddings are not silently missing.
When it happens
Trigger: POST /search/smart with queryAssetId for an asset whose SmartSearch embedding job has not yet run or failed; brand-new upload; an asset type that CLIP skips (e.g. some RAW files).
Common situations: SmartSearch queue is behind; asset was uploaded after the last embedding pass; CLIP job failed for that asset (corrupt decode); ML server was down during ingestion.
Related errors
- Smart search is not enabled
- Invalid CLIP dimension size: ${dimSize}
- Machine learning request '${JSON.stringify(config)}' failed
- May not request original file
- Asset media not found
AI-assisted analysis of immich-app/immich@199723261c (2026-08-12).
Data as JSON: /api/errors/2cf9bb520f9846a0.
Report an issue: GitHub.