immich-app/immich · error

Invalid value for 'size

Error message

Invalid value for 'size': ${pagination.size}

What it means

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.

Solutions

  1. Ensure pagination.size is a positive integer between 1 and 1000 before calling searchSmart
  2. Coerce/parse query params with Number() and validate, or clamp: Math.min(1000, Math.max(1, size))
  3. Provide a sane default (e.g. 100) when the caller omits size
  4. Return a 400 response at the controller layer with zod validation instead of a raw Error

Example fix

// before
await searchSmart({ size: Number(req.query.size) }, options);
// after
const size = Math.min(1000, Math.max(1, Number.parseInt(req.query.size ?? '100', 10) || 100));
await searchSmart({ size }, options);
Defensive patterns

Strategy: validation

Validate before calling

const parsed = z.int().min(1).max(1000).safeParse(pagination.size);
if (!parsed.success) throw new BadRequestException(`size must be an integer 1-1000`);

Type guard

function isValidSize(v: unknown): v is number {
  return typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 1000;
}

Try / catch

try {
  await searchSmart(pagination, options);
} catch (e) {
  if ((e as Error).message.startsWith("Invalid value for 'size'")) {
    return res.status(400).json({ error: 'size must be an integer between 1 and 1000' });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling searchSmart with pagination.size = 0, negative, > 1000, non-integer (e.g. 10.5), or undefined/NaN.

Common situations: 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.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/ae369f0efda7474f. Report an issue: GitHub.

Appendix: source

Thrown at server/src/repositories/search.repository.ts:319

  }

  // TODO(v4): remove with the deprecated flat-field search API
  @GenerateSql({
    params: [
      { page: 1, size: 200 },
      {
        takenAfter: DummyValue.DATE,
        embedding: DummyValue.VECTOR,
        lensModel: DummyValue.STRING,
        withStacked: true,
        isFavorite: true,
        userIds: [DummyValue.UUID],
      },
    ],
  })
  searchSmart(pagination: SearchPaginationOptions, options: SmartSearchOptions) {
    if (!z.int().min(1).max(1000).safeParse(pagination.size).success) {
      throw new Error(`Invalid value for 'size': ${pagination.size}`);
    }

    return this.db.transaction().execute(async (trx) => {
      await sql`set local vchordrq.probes = ${sql.lit(probes[VectorIndex.Clip])}`.execute(trx);
      const items = await searchAssetBuilderLegacy(trx, options)
        .select(columns.searchAsset)
        .innerJoin('smart_search', 'asset.id', 'smart_search.assetId')
        .orderBy(sql`smart_search.embedding <=> ${options.embedding}`)
        .orderBy('asset.id', 'asc')
        .limit(pagination.size + 1)
        .offset((pagination.page - 1) * pagination.size)
        .execute();
      return paginationHelper(items, pagination.size);
    });
  }

  @GenerateSql({
    params: [DummyValue.UUID],

View on GitHub (pinned to e55ac299a4)