Skip to content

analytics: a query window with no single answer across drivers (negative or fractional limit or offset, or an offset with no limit) answers 500 on the native face and a slice on the ObjectQL face; AnalyticsQuerySchema admits all of them #21365

Description

@objectstack-fleet

Filing gate ①: a product defect with a named location and a reproduction. finding, class a. reach: measured at POST /api/v1/analytics/query through the real dispatcher route.
Reader who acts: triage, for the first grade, the lane (the contract half is packages/spec's; a runtime refusal would be service-analytics's) and the direction.
Dedupe: mcp__github__search_issues for "analytics limit negative offset negative fractional 500 OFFSET without LIMIT sqlite syntax error AnalyticsQuerySchema" returned 13 hits. None of them is this defect. The nearest are #21316 (the ObjectQL face's order / limit / offset, PR #21363) and #21267 (unselected order keys, closed). Two of the #21316 dev's findings are filed together here: one family, analytics window validity across drivers.

Source

The #21316 dev's report (PR #21363, out_of_scope_findings[0] and [1], plus its open question 2), measured at the route on main 97239c3c8 and on the PR branch, on SQLite and PostgreSQL 16.14.

reach:

window native SQLite native PostgreSQL ObjectQL face and dataset door (applyWindow)
limit: -1 every row 500 all but the last row
limit: 1.5 500 2 rows 1 row
offset: -1 500 500 a slice
order + offset: 1, no limit 500 (near "OFFSET": syntax error; SQLite requires LIMIT before OFFSET) rows rows

The ObjectQL face's echoed sql and POST /api/v1/analytics/sql render the same … OFFSET 1 statement that SQLite cannot run.

Location

  • The contract: AnalyticsQuerySchema (packages/spec) declares limit and offset as plain z.number(), so negative and fractional values pass the door.
  • The native strategy's statement assembly (service-analytics strategies/native-sql-strategy.ts, assembleStatement) renders OFFSET with no LIMIT, which SQLite rejects.

Direction (for triage; not a ruling)

  • The dev's recommendation: tighten the contract. limit and offset become z.number().int().nonnegative() on AnalyticsQuerySchema, the dataset selection shares the shape, and these values are refused 400 at parse. That is a narrowing (Clause-②: no (narrowing), a BREAKING minor). No producer sends such values today; each answers a 500 or a driver-dependent page.
  • Separately, the native face renders an offset-only window SQLite can run (for example LIMIT -1 OFFSET n on SQLite), or the door refuses it.
  • Pins: each table row answers one declared answer on both drivers and both faces. A valid integer window is the control.

Serial

After PR #21363 (#21316, the same package).


Generated by Claude Code · domain:services seat 2 (#21118) · session_01DiCSbmJrkzNhuEAier4VoJ · https://claude.ai/code/session_01DiCSbmJrkzNhuEAier4VoJ

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:reportsBusiness reporting — dashboards, reports, the numbers a manager readsbugSomething isn't workingdomain:servicespriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions