Repository navigation
mctl_list_previews reports count 0 when the ArgoCD query fails #698
Description
Summary
When its ArgoCD query fails, mctl_list_previews reports {"count": 0, "items": []}. A failed read is presented as "no previews". In addition, the handler lists ArgoCD Applications, but previews are not ArgoCD Applications. So even a successful query cannot find them.
Observed (2026-10-18)
mctl_list_previews(team=labs, service=psa-smoke) returned:
{"count":0,"items":[],"note":"ArgoCD query failed: parsing argocd list response: missing items array"}At that moment a preview Helm release for labs/psa-smoke existed in labs-preview.
Defect 1: a failed read becomes an empty list
internal/api/handlers_read.go:683 (ListPreviews), origin/main:
:705:apps, err := h.opts.ArgoCD.ListApps(team):707-713:ErrUnauthenticatedreturns HTTP 200 withitems: [],count: 0and anerrorstring.:715-721:ErrForbiddenreturns HTTP 200 withitems: [],count: 0and anote.:722-728: any other error, includinginternal/argocd/client.go:364"missing items array", returns HTTP 200 withitems: [],count: 0and anote.
This breaks the workspace rule that "could not observe" is never "observed absent". A failed, partial or malformed read must surface as an error or an explicit unknown state, never as an empty set or a zero. Anything that checks count == 0, including an agent deciding whether a stale preview needs cleanup, is told there is nothing there. The MCP wrapper (internal/mcp/server.go:2107) passes the body through as a successful result.
Defect 2: the handler queries the wrong source of truth
- The handler (
handlers_read.go:703-705,:730-733) and the tool description (internal/mcp/server.go:2112-2115) assume preview ArgoCD Applications namedpreview-{team}-{service}-{id}. - mctl-gitops
wft-preview-deploydoes not create an ArgoCD Application. It runshelm upgrade --installdirectly into{team}-preview(mctl-gitopsplatform-gitops/argo-workflows/cluster-templates/wft-preview-deploy.yaml:357forNS="${TEAM}-preview"and:450forhelm upgrade --install). - The release name is
preview-${COMPONENT}-${PREVIEW_ID}(wft-preview-deploy.yaml:388), with no team segment. The handler's prefixpreview-{team}-{service}-could not match it even if such Applications existed.
So, as written, ListPreviews cannot return a preview created by mctl_create_preview, whether or not ArgoCD answers.
Proposed
- On any failed read (unauthenticated, forbidden, transport, malformed envelope), return an error: a non-2xx status and an MCP tool error. Do not return
count: 0. If a soft result is ever needed, use an explicit"state": "unknown"with nocountfield. - List from the actual source of truth: the Helm release Secrets (
owner=helm,name=preview-<service>-*) or the resources labelledmctl.ai/preview=true/mctl.ai/preview-idin{team}-preview, filtered by service. Then update the tool description to match. - Add tests for both: a failing backend yields an error and not
count: 0, and a release named the waywft-preview-deploynames it is listed.
Related: mctl-gitops wft-preview-deploy / wft-preview-delete, and the TTL issue filed alongside this one.
🤖 Generated with Claude Code
Activity
mctl-agents commentedon Oct 24, 2026
mctl-agents issue-investigator has analyzed this issue and created a proposal:
https://github.com/mctlhq/mctl-gitops/tree/main/platform-gitops/agents-state/mctl-api/proposals/issue-698-mctl-list-previews-reports-count-0-when/
Status:
proposed— pending human approval. Reviewrequirements.md,design.mdandtasks.md, then approve: signal this issue's DevLoopWorkflow (mctl-apiPOST /api/v1/agents/dev-loop/dev-loop-mctlhq-mctl-api-698/approve, orpython -m orchestrator.temporal.cli approve dev-loop-mctlhq-mctl-api-698 --approver <your-identity>) — the workflow flips.status.yamltoacceptedvia themctl-agents-approveoperation and runs the Tier 2 implementer. If no DevLoopWorkflow is running for this issue (pre-Temporal proposal), run themctl-agents-approveoperation directly withservice=mctl-api slug=issue-698-mctl-list-previews-reports-count-0-whenandexpected_content_digest=<digest>, the digest of the content you reviewed: in an mctl-gitops checkout,python3 scripts/proposal-content-digest.py --rev <reviewed-commit> platform-gitops/agents-state/mctl-api/proposals/issue-698-mctl-list-previews-reports-count-0-when. Without it the approve is refused (approval_content_unbound), and it is refused at the flip if the proposal changed after the commit you reviewed. See mctl-gitopsdocs/runbooks/proposal-approval-content-digest.md.The approver is recorded in
.status.yamland in the gitops commit, and the implementer refuses a proposal whosecontrol.requires_human_approvalcarries no named approver — so prefer the mctl-api endpoint, which takes the approver from the authenticated caller rather than from what the caller types.To approve with amendments, edit
requirements.md,design.mdortasks.mdon mctl-gitops main through a PR first. The edit supersedes the pending grant, and the loop asks for a decision on the new one: approve that, and the implementer works from the amended files. The approvereasonis recorded for audit only and never reaches the implementer, and@MCTL reinvestigatecarries no text, so neither can carry amendments.chore(agents): investigate mctlhq/mctl-api#698 2026-10-24
mctl-agents commentedon Oct 24, 2026
Approval grant
aar_de7b5b3c71b84faead66735b32184407was superseded because the proposal was rewritten. It was bound to digestsha256:1adbfbead21c5de822f7c6c9eab561a854e600c1d03c0eea1aa26b6bc3b78711; the current digest issha256:05b84be9018413add21db6225a81817b4493f70efc1536151f43c134986346ce. Please decide the fresh grantaar_4e94a2b2c89d4f2395a2b3f2e3a655c8.