{"record":{"id":"4368869ec6fd31d7","repo":"immich-app/immich","slug":"entity-not-found","errorCode":null,"errorMessage":"${entity} not found","messagePattern":"(.+?) not found","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/utils/misc.ts","lineNumber":114,"sourceCode":"const isMachineLearningEnabled = (machineLearning: SystemConfig['machineLearning']) => machineLearning.enabled;\nexport const isSmartSearchEnabled = (machineLearning: SystemConfig['machineLearning']) =>\n  isMachineLearningEnabled(machineLearning) && machineLearning.clip.enabled;\nexport const isOcrEnabled = (machineLearning: SystemConfig['machineLearning']) =>\n  isMachineLearningEnabled(machineLearning) && machineLearning.ocr.enabled;\nexport const isFacialRecognitionEnabled = (machineLearning: SystemConfig['machineLearning']) =>\n  isMachineLearningEnabled(machineLearning) && machineLearning.facialRecognition.enabled;\nexport const isDuplicateDetectionEnabled = (machineLearning: SystemConfig['machineLearning']) =>\n  isSmartSearchEnabled(machineLearning) && machineLearning.duplicateDetection.enabled;\nexport const isFaceImportEnabled = (metadata: SystemConfig['metadata']) => metadata.faces.import;\n\nexport const handlePromiseError = <T>(promise: Promise<T>, logger: LoggingRepository): void => {\n  promise.catch((error: Error | any) => logger.error(`Promise error: ${error}`, error?.stack));\n};\n\nexport const findOrFail = async <T>(find: () => Promise<T>, entity: string): Promise<NonNullable<T>> => {\n  const value = await find();\n  if (!value) {\n    throw new BadRequestException(`${entity} not found`);\n  }\n\n  return value;\n};\n\nexport async function* batched<T>(items: AsyncIterable<T>, size = JOBS_ASSET_PAGINATION_SIZE): AsyncGenerator<T[]> {\n  let batch: T[] = [];\n\n  for await (const item of items) {\n    batch.push(item);\n\n    if (batch.length >= size) {\n      yield batch;\n      batch = [];\n    }\n  }\n\n  if (batch.length > 0) {","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/utils/misc.ts#L96-L132","documentation":"findOrFail() is a helper that wraps an async lookup and converts a null/undefined result into a NestJS BadRequestException with '<entity> not found'. It centralizes not-found handling for repository lookups so callers get a clean 400 instead of propagating undefined.","triggerScenarios":"Any code path calling findOrFail with a finder function whose query matched no row, e.g. requesting a nonexistent asset/user/album ID via an API endpoint.","commonSituations":"Client requesting an asset that was deleted server-side or belongs to another user; stale IDs cached in a client; typos in IDs; race where the entity is removed between listing and fetching.","solutions":["Verify the requested entity ID exists (and belongs to the authenticated user) before the call.","Refresh client-side state/list to drop stale references to deleted entities.","If the entity is legitimately optional, use the raw find call instead of findOrFail and handle null yourself.","Check the message prefix ('<entity> not found') to identify which lookup failed and fix the upstream data."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const exists = asset && (await repo.get(asset.id)) !== null;\nif (!exists) return null; // avoid triggering not-found","typeGuard":"const isNotFound = (e: unknown): e is BadRequestException =>\n  e instanceof BadRequestException && / not found$/.test(e.message);","tryCatchPattern":"try { const user = await findOrFail(() => repo.get(id), 'User'); } catch (e) { if (isNotFound(e)) return res.status(404).json({ error: 'User not found' }); throw e; }","preventionTips":["Validate IDs before lookup where possible","Treat 404 as expected for user-facing lookups, not as a bug","Refresh client caches to drop references to deleted entities"],"tags":["not-found","api","nestjs"],"backgroundTag":"entity-not-found","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}