Skip to content

Warn the model when SQL results are truncated by a LIMIT/TOP clause#863

Draft
Bl3f wants to merge 1 commit into
mainfrom
cursor/warn-on-sql-limit-truncation-62da
Draft

Warn the model when SQL results are truncated by a LIMIT/TOP clause#863
Bl3f wants to merge 1 commit into
mainfrom
cursor/warn-on-sql-limit-truncation-62da

Conversation

@Bl3f
Copy link
Copy Markdown
Contributor

@Bl3f Bl3f commented May 28, 2026

Problem

When the agent writes a SQL query with a LIMIT clause (e.g. LIMIT 20), the warehouse returns exactly that many rows. The execute_sql tool output reports row_count = 20, and nothing signals to the model that the result was capped by its own SQL. The agent then confidently states things like "there are exactly 20 games added in 2026" when the true count is 509.

The system already handles its own 40-row display cap correctly (it shows the true total plus a pagination hint), but it had no way to distinguish a SQL-imposed LIMIT from a complete result set.

Fix

Detect a row limit imposed by the outermost query and warn the model when the returned row count hits that limit.

  • detectQueryRowLimit() in sql-filter.ts parses the outermost LIMIT n, LIMIT offset, n, LIMIT n OFFSET m, TOP n / TOP (n) (ignoring TOP n PERCENT), and FETCH FIRST n ROWS ONLY. It masks string literals and subquery parentheses so it only sees the outer query's limit.
  • execute_sql now sets applied_limit on its output when a top-level limit is detected.
  • ExecuteSqlOutput renders a clear warning to the model when row_count >= applied_limit: the count reflects the LIMIT, not the total, and the model should run a COUNT(*) query without a LIMIT to get the true total. The row_count >= applied_limit guard means aggregates over limited subqueries (e.g. SELECT count(*) FROM (... LIMIT 20)) do not produce false warnings.
  • Added a SQL Query Rules system-prompt rule reinforcing that a LIMIT/TOP clause caps returned rows, not existing rows.

Model-facing output (reproducing the reported scenario)

For ... ORDER BY total_downloads DESC LIMIT 20 returning 20 rows, the model now sees:

Warning: this query returned exactly 20 rows, the maximum allowed by its LIMIT/TOP clause, so the result is almost certainly truncated. This row count reflects the LIMIT, NOT the total number of matching rows — do not report it as a total or "exact" count. To get the true total, run a separate query with COUNT(*) (or COUNT over a subquery) and no LIMIT/TOP clause.

limit_warning_demo.log

Testing

  • npm run -w @nao/backend test -- sql-filter execute-sql — 30 tests pass (12 new detection cases + 2 new output cases).
  • npm run lint — passes across backend, frontend, shared.

Pre-existing, unrelated failures in system-prompt.test.ts (timezone), sqlite.test.ts (native bindings), and compaction.test.ts were confirmed to fail on the clean base as well.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

@github-actions
Copy link
Copy Markdown
Contributor

🚀 Preview Deployment

URL https://pr-863-4b00e9d.preview.getnao.io
Commit 4b00e9d

⚠️ No LLM API keys configured - you'll see the API key setup flow when trying to chat.


Preview will be automatically removed when this PR is closed.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants