Repository navigation
Description
What happens
GET /flocks returns the first 100 flocks ordered by name (DefaultPageSize = 100, MaxPageSize = 500 in src/Cluckwork.Api/Endpoints/Flocks/FlockEndpoints.cs:17-18; OrderBy(f => f.Name).ThenBy(f => f.Id) then Skip/Take in FlockRepository.ListAsync).
Five screens call listFlocks() without a limit and render the result straight into a control with no paging:
| Screen | Call | Archived counted? |
|---|---|---|
DailyEntryPage.tsx:124, :401 |
listFlocks() |
no |
HistoryPage.tsx:121 |
listFlocks({ includeArchived: true }) |
yes |
FeedPage.tsx:96 |
listFlocks({ includeArchived: true }) |
yes |
WaterPage.tsx:101 |
listFlocks({ includeArchived: true }) |
yes |
UsersPage.tsx:166 |
listFlocks() |
no |
Three others already raise it to the maximum, which is what makes this look like an oversight rather than a decision:
FlocksPage.tsx:93—limit: 500ExpensesPage.tsx:158—limit: 500Dashboard.tsx:48—limit: MAX_PAGE(500)
Why it matters
A farm with more than 100 flocks (or more than 100 including archived, on the three screens that ask for those) cannot record a daily entry for the flocks that fall outside the first page. The affected flock is simply absent from the dropdown — no message, no "showing 100 of N", nothing to distinguish it from a flock that does not exist.
Which flocks disappear is alphabetical, not recent-or-old, so it will not look like a paging problem to whoever hits it. A farm that names flocks Barn A…/Barn B… loses the end of the alphabet.
The includeArchived: true screens are the more likely to bite first: archived flocks accumulate permanently and are never cleaned up, so the 100 fills with history.
How this surfaced
Not from a farm — from the E2E suite. manager.spec.ts creates a flock per run named E2E …; they cluster alphabetically and the newest sorts last, so it is the first one truncated. After ~100 accumulated runs the spec could no longer find the flock it had just created, and the failure read as a bare Expected 1, Received 0 on an unrelated-looking assertion. PR #504 added a diagnostic message pointing at reset.sh; this issue is the product half, which that PR deliberately did not touch.
Options
- Pass
limit: 500on the five screens, matching the three that already do. Smallest change, consistent with existing practice, still a silent cliff at 500. - Make the cliff visible — if the response fills the page, say so next to the control ("showing the first 100 flocks"). Cheap, and turns a silent wrong answer into a visible limitation.
- Make the pickers searchable/paged. Correct, and considerably more work; probably only worth it if a real farm approaches these numbers.
1 + 2 together seem like the honest minimum: it removes the realistic case and stops the remaining one being silent.
Not verified
I have not confirmed what a real farm's flock count looks like, so I cannot say whether 100 is close to reachable in practice or purely theoretical. If it is theoretical, option 2 alone may be enough. The mechanism above is read from the code and confirmed by the E2E failure; the impact estimate is not measured.
Implementation order
This issue is not a separate implementation step. Its picker defects are covered by #512.
- Implement Page truncated customer and movement tables with the shared usePagedList hook #511 first: adopt the existing
usePagedListhook for the truncated customer and movement tables/ledgers. - Implement Add a reusable searchable paged entity picker for flock and customer selectors #512 second: add and adopt the reusable searchable paged entity picker.
- The Add a reusable searchable paged entity picker for flock and customer selectors #512 implementation PR should close both Add a reusable searchable paged entity picker for flock and customer selectors #512 and this issue.
Do not land the temporary limit: 500 workaround from the options above as an intermediate step unless this order is explicitly reprioritized; #512 replaces that workaround with full reachability.
Related issues
- Add a reusable searchable paged entity picker for flock and customer selectors #512 — reusable picker implementation that covers and should close this issue.
- Page truncated customer and movement tables with the shared usePagedList hook #511 — preceding sibling group for paged customer and movement tables/ledgers.
Simulation coverage
The durable regression fixture for this defect belongs to #512, not to a separate implementation here. #512 must extend the simulation seed beyond the flock page boundary and exercise a deterministic late-sorting flock through the real picker. The fixture must update the simulation manifest's exact expected counts/fingerprint and remain idempotent and fail-closed.
Activity
mforce commentedon Sep 2, 2026
Verified against the tree at
39de7bd7. This is covered by #642 (#512) for the defect it was filed about, per this issue's own implementation order ("#512 replaces that workaround with full reachability").What #642 actually closed, checked line by line rather than by reading its description:
FlockPicker, which is searchable and server-paged:DailyEntryPage.tsx:586,HistoryPage.tsx:521,FeedPage.tsx:243/:315,WaterPage.tsx:316/:424,UsersPage.tsx:930. No flock is absent from a control any more, so the headline failure — "cannot record a daily entry for the flocks that fall outside the first page" — is gone.flockNamefrom the endpoint's scoped bulk read (cluckwork.ts:713,:747,:813), so a row for an out-of-window flock renders its name, not an id fragment.HistoryPage.rowFlockNamefalls back to the capped list only for an older server that omits the field.HistoryPage.flockEditablereads the row's ownflockStatusand only falls back to the capped catalog when the field is absent — so a flock outside the window no longer silently loses its edit link.id.slice(0, 8).What is left, and why it does not hold this issue open. Three screens still take a default selection from the capped
listFlocks()result —WaterPage.tsx:211,UsersPage.tsx:258,DailyEntryPage.tsx:202. On a farm with more than 100 flocks those defaults come from the first alphabetical page. Nothing is unreachable and the default is visible before it is committed, so this is a poor default rather than a wrong answer. Filed as #646 so it is a tracked follow-up and not a criterion left to rot in a closed issue.The
limit: 500workaround from this issue's Options is deliberately not landed, exactly as the implementation order asked.Simulation coverage went with #512:
tools/simulation/ui/specs/named-entity-picker.spec.ts.mforce commentedon Sep 2, 2026
Closing as covered by #642 (#512), per the verification above. Residual default-selection work is #646.