{"record":{"id":"ae369f0efda7474f","repo":"immich-app/immich","slug":"invalid-value-for-size-pagination-size","errorCode":null,"errorMessage":"Invalid value for 'size': ${pagination.size}","messagePattern":"Invalid value for 'size': (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/repositories/search.repository.ts","lineNumber":319,"sourceCode":"  }\n\n  // TODO(v4): remove with the deprecated flat-field search API\n  @GenerateSql({\n    params: [\n      { page: 1, size: 200 },\n      {\n        takenAfter: DummyValue.DATE,\n        embedding: DummyValue.VECTOR,\n        lensModel: DummyValue.STRING,\n        withStacked: true,\n        isFavorite: true,\n        userIds: [DummyValue.UUID],\n      },\n    ],\n  })\n  searchSmart(pagination: SearchPaginationOptions, options: SmartSearchOptions) {\n    if (!z.int().min(1).max(1000).safeParse(pagination.size).success) {\n      throw new Error(`Invalid value for 'size': ${pagination.size}`);\n    }\n\n    return this.db.transaction().execute(async (trx) => {\n      await sql`set local vchordrq.probes = ${sql.lit(probes[VectorIndex.Clip])}`.execute(trx);\n      const items = await searchAssetBuilderLegacy(trx, options)\n        .select(columns.searchAsset)\n        .innerJoin('smart_search', 'asset.id', 'smart_search.assetId')\n        .orderBy(sql`smart_search.embedding <=> ${options.embedding}`)\n        .orderBy('asset.id', 'asc')\n        .limit(pagination.size + 1)\n        .offset((pagination.page - 1) * pagination.size)\n        .execute();\n      return paginationHelper(items, pagination.size);\n    });\n  }\n\n  @GenerateSql({\n    params: [DummyValue.UUID],","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/repositories/search.repository.ts#L301-L337","documentation":"searchSmart validates pagination.size with zod (z.int().min(1).max(1000)) before running a vector search transaction. It throws when size is not an integer between 1 and 1000, because the pgvecto.rs/vchord vector query would misbehave or return unbounded results with an invalid limit.","triggerScenarios":"Calling searchSmart with pagination.size = 0, negative, > 1000, non-integer (e.g. 10.5), or undefined/NaN.","commonSituations":"Clients sending missing or unparsed query params (size comes in as a string or undefined), UI paging past the allowed cap, or a caller defaulting size incorrectly.","solutions":["Ensure pagination.size is a positive integer between 1 and 1000 before calling searchSmart","Coerce/parse query params with Number() and validate, or clamp: Math.min(1000, Math.max(1, size))","Provide a sane default (e.g. 100) when the caller omits size","Return a 400 response at the controller layer with zod validation instead of a raw Error"],"exampleFix":"// before\nawait searchSmart({ size: Number(req.query.size) }, options);\n// after\nconst size = Math.min(1000, Math.max(1, Number.parseInt(req.query.size ?? '100', 10) || 100));\nawait searchSmart({ size }, options);","handlingStrategy":"validation","validationCode":"const parsed = z.int().min(1).max(1000).safeParse(pagination.size);\nif (!parsed.success) throw new BadRequestException(`size must be an integer 1-1000`);","typeGuard":"function isValidSize(v: unknown): v is number {\n  return typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 1000;\n}","tryCatchPattern":"try {\n  await searchSmart(pagination, options);\n} catch (e) {\n  if ((e as Error).message.startsWith(\"Invalid value for 'size'\")) {\n    return res.status(400).json({ error: 'size must be an integer between 1 and 1000' });\n  }\n  throw e;\n}","preventionTips":["Always clamp page sizes: Math.min(1000, Math.max(1, size))","Validate query params with zod at the controller boundary","Never pass raw string query params as numeric options","Default missing size to a fixed constant"],"tags":["validation","zod","pagination"],"backgroundTag":"value-out-of-range","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"}