Skip to content

fix(cli,support,scaletest): terminate workspace paging on server count - #28027

Closed
jscottmiller wants to merge 2 commits into
mainfrom
scott/plat-386-workspace-pagination-correctness
Closed

fix(cli,support,scaletest): terminate workspace paging on server count#28027
jscottmiller wants to merge 2 commits into
mainfrom
scott/plat-386-workspace-pagination-correctness

Conversation

@jscottmiller

@jscottmiller jscottmiller commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

convertWorkspaces in coderd/workspaces.go drops rows whose build or template
the caller cannot read, but /api/v2/workspaces applies its limit in SQL and
reports Count from before the limit and offset. A page can therefore be shorter
than the requested limit while rows remain.

Five paging loops assumed the opposite. Four stopped on a short or fully filtered
page and truncated their results; support/support.go also advanced the offset by
the number of rows returned, re-requesting rows it had already collected. Each loop
now advances the offset by the requested page size and stops once it reaches
Count.

  • support/support.go
  • cli/configssh.go (--no-wildcard)
  • cli/exp_scaletest.go (getScaletestPrebuildWorkspaces, getScaletestWorkspaces)
  • scaletest/prebuilds/run.go (allWorkspacesForTemplate)

convertWorkspaces also now warns with the dropped count split by reason. The
discrepancy was previously invisible: nothing logged it, and no response field
distinguished a filtered page from an exhausted one.

Testing

  • make pre-commit
  • go test ./support/ -run TestRun
  • go test ./cli/ -run TestConfigSSH
Reachable drop paths

workspaceData fetches builds and app statuses as AsSystemRestricted, and a
workspace and its first build are inserted in one transaction, so a missing build
is not reachable in practice. Templates come from GetTemplatesWithFilter, which
is authz-filtered and hardcodes deleted = false, giving two real causes:

  • Deleted template with surviving workspaces. deleteTemplate permits
    deletion when only prebuild workspaces remain and defers cleanup to the
    reconciler, so for that window a deployment-wide listing counts prebuilds that
    conversion then drops.
  • Unreadable template. The org-member floor role grants no template.read, so
    member access comes from the default everyone-group ACL. Disabling that access,
    editing the ACL, removing a user from a group, or sharing a workspace with a user
    who lacks template access strands existing workspaces permanently.

A single dropped row anywhere before the last page was enough to truncate the rest,
so the impact does not scale with the number of unreadable rows. It requires the
caller's authorized set to exceed the page size: 100 for config-ssh, 200 for
support bundle.


This pull request was created by Coder Agents on behalf of @jscottmiller.

The workspaces endpoint applies its limit in SQL and then drops rows whose
build or template the caller cannot read, so a page can be shorter than the
requested limit without the result set being exhausted. Terminating on a short
page truncated the results, and advancing the offset by the number of rows
returned re-requested rows that had already been collected.

Each loop now advances the offset by the requested page size and stops once it
reaches the total the response reports.
@jscottmiller jscottmiller added the experimental Changes that might not necessarily be merged, until its approved to proceed with. label Aug 11, 2026
@linear-code

linear-code Bot commented Aug 11, 2026

Copy link
Copy Markdown

PLAT-386

@github-actions github-actions Bot locked and limited conversation to collaborators Aug 11, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

experimental Changes that might not necessarily be merged, until its approved to proceed with.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant