{"record":{"id":"4368869ec6fd31d7","repo":"immich-app/immich","slug":"entity-not-found","errorCode":null,"errorMessage":"${entity} not found","messagePattern":"(.+?) not found","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/utils/misc.ts","lineNumber":117,"sourceCode":"  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 isConnectionAborted = (error: Error | any) => error.code === 'ECONNABORTED';\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":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/utils/misc.ts#L99-L135","documentation":"Generic helper findOrFail in server/src/utils/misc.ts: it runs an async find() and throws BadRequestException (`${entity} not found`) if the result is null/undefined. Callers pass an entity label for the message. It is the server-side counterpart of a 404-as-400 used to assert a referenced resource exists.","triggerScenarios":"Any code path that calls findOrFail(findFn, 'Entity') where findFn resolves to null/undefined — e.g. looking up a person, partner, album, or shared link by id that does not exist or is not visible to the caller.","commonSituations":"Client passes an id that was deleted or never existed; permission-filtered query returns nothing because the resource belongs to another user; race condition where the resource is deleted between listing and the operation.","solutions":["Inspect the error's entity name to know which resource was missing, then verify that id exists for the caller.","Refresh the client-side list/cache and retry with a valid id.","If the resource was deleted intentionally, update the UI to remove the stale reference."],"exampleFix":"// the throw is generic; fix the caller, e.g.\n// before\nconst person = await findOrFail(() => repo.getByPersonId(maybeId), 'Person');\n\n// after\nconst exists = await repo.existsByPersonId(maybeId);\nif (!exists) return null;\nconst person = await findOrFail(() => repo.getByPersonId(maybeId), 'Person');","handlingStrategy":"try-catch","validationCode":"// pre-check existence using the same finder before calling findOrFail\nconst candidate = await find();\nif (!candidate) { /* handle missing resource gracefully */ }","typeGuard":"const isPresent = <T>(v: T | null | undefined): v is T => v != null;","tryCatchPattern":"try { return await findOrFail(() => repo.getById(id), 'Entity'); }\ncatch (e) { if (e instanceof BadRequestException && /not found$/.test(e.message)) return null; throw e; }","preventionTips":["Validate resource ids at the API boundary before lookups.","Where possible use a nullable-returning finder and branch, reserving findOrFail for genuinely invariant cases."],"tags":["validation","not-found","helper","bad-request","generic"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}