fix(api): query pagination accepts non-integer limit/page → fractional OFFSET/LIMIT
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 76/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- typescript
- 領域
- api, backend, databases, testing-qa
調査の方向性
apps/api/src/schemas/query-schemas.ts と apps/api/src/routes/query.ts の DynamicQueryRequestSchema と validatePaginationFields から始め、次に packages/ai/src/query/index.ts の QuerySchema と limit/offset のビルダーを調べます。issue に記載されている小数値の入力を再現し、リグレッションテストを追加します。limit/page の値が有限でない、または整数でない場合に期待される 400 のバリデーションレスポンスを受け取り、有効なページネーションでは引き続き整数互換の句が構築されれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
POST /v1/query DynamicQueryRequest accepts non-integer limit/page without validation and produces fractional LIMIT/OFFSET that fail ClickHouse Int32 binding.
Affected code:
apps/api/src/schemas/query-schemas.ts:49-50DynamicQueryRequestSchema: t.Optional(t.Number())— nominimum/integerconstraint.apps/api/src/routes/query.ts:294-308validatePaginationFieldsonly checks<1and>10000/<1forpage, notNumber.isInteger/isFinite.apps/api/src/routes/query.ts:1040-1041limit: request.limit || 100,offset: request.page ? (request.page-1)*(request.limit||100) :0→ withlimit=1.5, page=1.5yieldsoffset=0.75(fractional).packages/ai/src/query/simple-builder.ts:1148-1154buildLimitClause/buildOffsetClauseemitLIMIT 1.5 OFFSET 0.75vs. buildersLIMIT {limit:Int32} OFFSET {offset:Int32}(packages/ai/src/query/builders/pages.ts:182,sessions.ts:318, etc.).- Internal
packages/ai/src/query/index.ts:61-62QuerySchema: z.number().min(1).max(1000)also allows floats (missing.int()).
To Reproduce
- Authenticated request:
POST /v1/query?website_id=<id>&timezone=UTC
Content-Type: application/json
{
"parameters": ["top_pages"],
"startDate": "2026-01-01",
"endDate": "2026-01-02",
"limit": 1.5,
"page": 1.5
}
- Also try
{"limit": 0.5},{"page": 1.5},{"limit": 1.5, "page": 2.3}.
Expected behavior
400 VALIDATION_ERROR with details like:
{ "field":"limit", "message":"Limit must be an integer" }
{ "field":"page", "message":"Page must be an integer" }
limit/page should require finite integer, limit 1..10000, page 1...
Actual behavior
No validation error; request reaches ClickHouse with fractional values. Reproduced locally with copy of validatePaginationFields (D:\tmp\repro_pagination.js):
float limit {limit:1.5} => errors=[] limit=1.5 offset=0 BUG non-integer passed
float page {page:1.5} => errors=[] limit=100 offset=50 BUG
both float => offset 0.75 BUG not integer
Infinity/NaN similarly slip through (JSON NaN not encodable but Elysia coercion from query string can produce floats).
buildLimitClause(NaN) → '' (unbounded), buildLimitClause(0) → ''.
Screenshots
N/A
Environment
- OS: Windows, Bun 1.4.2 (
package.json:30[email protected]pinned) - Commit:
92c15273d(origin/staging)
Additional context
limitdefault fallback|| 100masks0/NaNinapps/api/src/routes/query.ts:1040,simple-builder.ts:1149fallback similarly.limitmax mismatch: API allows10000(validatePaginationFields:301), internalQuerySchemaallows1000— not part of this bug but worth aligning.- No existing open issue covers this (checked
gh issue list). - Minimal fix proposal: tighten
DynamicQueryRequestSchema(TypeBoxminimum), addNumber.isInteger/isFiniteinvalidatePaginationFields, add.int()toQuerySchema(packages/ai/src/query/index.ts:61-62), add regression test.
AI disclosure
Issue drafted with assistance from Muse Spark (opencode/muse-spark-1.2-contributor-free) and human-verified via local reproduction (node D:\tmp\repro_pagination.js).
- 主要言語
- TypeScript
- スター
- 1.2k
- フォーク
- 227
- PR マージ指標
- 30日以内にマージされた PR はありません
環境構築
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
似ている issue
-
Navbar avatar and name stay stale after saving profile changes対応中かも @alexechoi が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
marmelab/atomic-crm#416 ·
メンテナーはふだん 1 日以内に返信
-
feature-request
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
bluesky-social/social-app#12343 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
lucide-icons/lucide#5165 ·
メンテナーはふだん 1 日以内に返信
-
[Feature] Preferences - Keep the theme selection popover open after selection for quick previewオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 64/100
marktext/marktext#6033 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
area:desktop bug has repro platform:macos
難易度 2/5 1〜3時間 初心者へのやさしさ 62/100
anthropics/claude-code#107903 ·