2026-10-21-bounded-lists
title: Bound whole lists and the reads behind them affects: dartway_core_shared: "0.23.0" dartway_core_server: "0.23.0" dartway_cli: "0.26.0"
Who is affected
Every project with a DwListRequest. Its new inherited maxItems member can collide with a
project's existing request field of that name (see step 4). A whole-list handler using readWhole
serves all rows in production, warning past its bound (200 unless the class names another).
Two things are new to see:
- a server test whose
listhandler answers more thanmaxItemsitems now fails the call:DwTestServeris strict about the bound; dartway checkwarnsunboundedReadfor a repositoryfind(…)in a request handler of a*_handlers.dartthat names neitherlimit:norunbounded:.
What to change
-
Make a development server as strict as the tests. In
deploy/config.yaml, underlocal:+ DW_STRICT_BOUNDS: trueand pass it to the settings in
<project>_server/bin/server.dart:settings: DwServerSettings(…+ strictBounds: env.server.strictBounds,), -
For each
unboundedReadwarning, decide what the read is:-
a list that grows with use — tasks, messages, history — becomes a
DwPageRequest,DwTableRequestorDwWindowRequest(thedartway-contractskill,requests.md); -
every list the domain bounds reads through the server helper:
request.readWhole((limit) =>ctx.db.<table>.find(where: …, orderBy: …, limit: limit))Apply the nullable
limitto the same query; null means no limit. The callback only reads and may run twice. The normal read probes withfetchLimit(maxItems + 1). Overflow throws in tests and strict development, naming the request and observed probe count. Production re-reads once without a limit, serves all rows and logs the true count and size through the existing throttled warning. Do not return afetchLimitprobe as the answer: that truncates. -
a read the domain keeps small that is not a list's answer says why, beside the read:
ctx.db.<table>.find(where: …, unbounded: 'a board has a handful of columns')
-
-
A list that legitimately holds more than 200 items raises its bound in its class, with the reason in one line of its doc comment:
/// … At most 500: a club schedules about three weeks ahead.const ListUpcomingSessions({required this.from}) : super(maxItems: 500); -
If a project request already declares a field named
maxItems, rename that field and its constructor argument to a domain name such asresultLimit. Update call sites, handler reads, validation and tests, then rundartway generateto regenerate codecs and the project contract descriptor. Keep the inheritedmaxItemsfor the framework bound, passed throughsuper. This project-field rename changes the project's JSON contract: advance its shared package's breaking version line and deploy matching app and server using the normal contract procedure. Do not overridemaxItemswith a client-supplied field or hand-edit generated files. The framework runtime wire anddwProtocolVersionare unchanged.
How to check
dartway check --type unboundedRead from <project>_flutter reports nothing,
and dartway test is green. A server started with bin/server.dart logs no
answered … items, past its bound and no (largeResponseBytes) warning for the project's own
screens; a production log that shows either names the request to page.