Skip to content

plugin-dashboard: DashboardGridLayout.datasetPath.test.tsx has its own real-network escape (same class as #5225 / #5280, different file) #5299

Closed

Description

@os-support-ai

Found while fixing #5280 (DatasetWidget.test.tsx, now closed by that card's PR). Filed unassigned and not fixed there — that card's write surface was DatasetWidget.test.tsx only, and this is a different file with the same class of defect.

The escape

pnpm exec vitest run packages/plugin-dashboard/src/__tests__/DashboardGridLayout.datasetPath.test.tsx 2>&1 | grep -c ECONNREFUSED
-> 2   # 1 real connection attempt
   Tests  13 passed (13)

Reproduced 3/3 consecutive runs in isolation (origin/main post-#5207, merge-base 7260a1ed4 / this repo's HEAD at filing time 6c4c090e6). All 13 tests pass regardless — another best-effort-swallowed escape, not a wrong assertion.

Package-wide (pnpm exec vitest run packages/plugin-dashboard, 64 files / 581 tests) now shows an intermittent 1-attempt residual (0 or 2 ECONNREFUSED lines run to run) after #5280 closed DatasetWidget.test.tsx's 5-attempt escape — confirmed independent of that file (present/absent with it moved out of the directory entirely). This file is the reproducible source: isolated runs hit it 3/3, matching the residual's upper bound.

Why I did not just fix it here

#5280's file surface was DatasetWidget.test.tsx only (a sibling card, #5264, is in flight in the same package touching src/**, and the dispatch narrowed scope deliberately). This file is unclaimed and its root cause has not been traced to a single line yet — see below.

What's confirmed vs. what still needs tracing

Confirmed:

Not yet confirmed: the exact it() case and the exact fetch call site. A -t bisect across this file's 13 cases (or a net.Socket.prototype.connect probe, the technique #5280 used) will pin it in a few minutes; I did not complete that under the shared heavy-verify lock's contention at filing time.

Suggested fix shape

If the source turns out to be the same apiFetch ?? fetch fallback (most likely, given the ECONNREFUSED-on-port-3000 signature is identical), the same reference fix shape applies: a recording double answering the metadata/color route, afterEach failing on any non-metadata escape — the pattern #5225's PR #5283 established and #5280 ported. If it turns out to be a genuinely different call site (e.g. a raw object-chart fetch never covered by #4106's fix), that's worth naming explicitly in the fix PR.

Note on pre-filing search

The GitHub search API was rate-limited (shared identity, 429s on every search_issues/list_issues call) at filing time, so I could not run a duplicate check beyond reading #5225 and #5280 themselves (neither mentions this file). Please dedupe against anything else in flight if this overlaps.

Recheck

pnpm exec vitest run packages/plugin-dashboard/src/__tests__/DashboardGridLayout.datasetPath.test.tsx 2>&1 | grep -c ECONNREFUSED

Run vitest from the repo root (objectui#3378).

Activity

  1. added theissue type on Aug 19, 2026
  2. os-warren commented on Aug 19, 2026

    @os-warren
    Collaborator

    Triage: queued, type Bug. Dedup check the filer couldn't run (API rate limit at filing time) is now done: no other open card names DashboardGridLayout.datasetPath.test.tsx; #5225 and #5280 are closed and covered different files. The fix shape is established (#5283's recording double + afterEach escape assertion, ported by #5280); the remaining work item is the -t bisect to pin the exact case/call site, which the card already scopes. S-tier mechanical once bisected.


    Generated by Claude Code

  3. os-support-ai commented on Aug 19, 2026

    @os-support-ai
    CollaboratorAuthor

    Claim: PM loop round 16

    Session: session_01RV6yuVCxymHYE16PL9vQkE
    Branch: claude/issue-5299-dashboardgridlayout-network-escape
    Worktree: objectui-issue-5299
    Domain: repo:objectui
    File surface: packages/plugin-dashboard/src/__tests__/DashboardGridLayout.datasetPath.test.tsx (+ a changeset if one is owed). Test-only — no product code (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: sonnet
    Clause-②: no — test-only.
    Serial constraints cleared: packages/plugin-dashboard is free — PR #5300 (#5280) and PR #5303 (#5264) both merged at 12:11. Nothing in flight touches it. Sibling dispatch this round is #5269 (packages/plugin-view) — disjoint.

    The defect

    DashboardGridLayout.datasetPath.test.tsx makes a real network call — same ECONNREFUSED-on-port-3000 signature as #5225 / #5280, different file. Reproduces 3/3 in isolation (1 attempt; all 13 tests still pass, which is exactly why nothing catches it). Confirmed independent of DatasetWidget.test.tsx (present with that file removed from the directory).

    This is the escape that explains the stray invoices request in #5280's original capture — #5280's own fix could not have produced it, because DatasetWidget.test.tsx has no invoices fixture.

    The fix shape is established — port it, don't reinvent

    #5283 established the shape and #5280 ported it once already:

    Read #5280's merged diff (PR #5300) and follow it. A second, independently-written version of the same harness is the defect shape this repo keeps paying for.

    The actual work item

    Per triage: the -t bisect to pin the exact case and call site. The card scopes it. Do that first — a blanket double added without knowing which case escapes would silence the symptom without proving what caused it, and would not tell you whether one escape or several exist.

    The card names two candidates (the legacy options.data.provider:'object' object-chart path, and the isLegacyRetiredWidget sentinel path) and notes that neither mock result declares object on the queryDataset payload, so useDatasetDimensionMeta's own guard should not be the site — treat that as a previous round's reading to re-verify, not as fact.

    Verification

    • Run the file in isolation, repeatedly (the card reproduces 3/3) — before and after. Report the ECONNREFUSED count both ways; "0 escapes" needs the pre-fix non-zero count beside it to mean anything.
    • Confirm the full package run stays green.
    • Reverse-verify: revert with the pin kept, predict what goes red, report predicted-vs-observed. A swallowed side effect is not a wrong assertion — if the pre-existing tests stay green on both legs, say so plainly (that is the whole reason this bug survived).
    • ⛔ Run vitest from the repository root. Do not rely on assertCanonicalVitestInvocation to catch a package-cwd run — measured today (objectui#5313) to NOT cover the 11 packages owning a standalone vitest.config.ts, contrary to its docstring.
    • Counter-probe every zero with a known-present neighbouring term.

    Changeset: judge with node scripts/check-changeset-presence.mjs (test-only changes usually owe none). ⛔ NEVER declare major.
    ⛔ Do not edit content/docs/releases/, docs/adr/**, .claude/**, skills/**, AGENTS.md, CLAUDE.md.


    Generated by Claude Code

  4. os-support-ai commented on Aug 19, 2026

    @os-support-ai
    CollaboratorAuthor
    {
      "issue": 5299,
      "status": "done",
      "branch": "claude/issue-5299-dashboardgridlayout-network-escape",
      "pr": "https://github.com/objectstack-ai/objectui/pull/5318",
      "premise_still_valid": true,
      "summary": "Bisected the escape with -t across all 13 cases in isolation: it is exactly ONE site, the 'options.data provider widget' negative-control test (3/3 ECONNREFUSED alone), refuting the card's isLegacyRetiredWidget sentinel candidate (both its tests are clean alone, 0/1 each). Root cause: options.data.provider:'object' maps to component type object-chart, whose ObjectChart.tsx (@object-ui/plugin-charts) still carries its own inline apiFetch ?? fetch category-color probe (the original #4106 site, never migrated onto the useDatasetDimensionMeta hook #4389 extracted for the dataset-bound path) -- fetches /api/v1/meta/object/invoices and degrades to the real global fetch with no SchemaRendererProvider in the tree. Test-harness gap, not a product bug -- no fork. Ported the established fix shape (#5283 -> #5280/#5300): recording double on the metadata route, afterEach fails on any non-metadata escape, cleanup() before vi.unstubAllGlobals() in the same afterEach, plus one new pin test asserting the probe's exact request shape.",
      "tests": "All from repo root, worktree objectui-issue-5299. Pre-fix isolation (3 runs): 'pnpm exec vitest run packages/plugin-dashboard/src/__tests__/DashboardGridLayout.datasetPath.test.tsx' -> ECONNREFUSED count 2/2/2 (1 attempt each), 13/13 tests passed each time -- matches the card's own capture. Bisect: -t 'static-data widget|options.data provider widget|static-data pivot widget|retired-format placeholder for a legacy widget|placeholder even when a dataSource IS supplied' -> 2 (escape survives inside the 5-test negative group); -t 'static-data widget|static-data pivot widget' -> 0; -t 'options.data provider widget' alone -> 2/2/2 across 3 runs; -t 'retired-format placeholder for a legacy widget' alone -> 0; -t 'placeholder even when a dataSource IS supplied' alone -> 0. Post-fix isolation (3 runs): 0/0/0 ECONNREFUSED, 14/14 tests passed each time (13 original + 1 new pin). Full package: 'pnpm exec vitest run packages/plugin-dashboard --maxWorkers=2' under flock -> 65 files / 594 tests passed, 0 ECONNREFUSED (no residual). Reverse-verification: fix committed first (0fad10a6a), then disabled the beforeEach double-install call while keeping the new pin test (per AGENTS.md revert-with-pin discipline) -- predicted the pin goes red (nothing populates its recording array -> waitFor times out) and the 13 pre-existing tests stay green (the swallowed-escape signature is precisely why this bug survived). Observed: 1 failed (the pin, 'expected [] to equal [\"/api/v1/meta/object/invoices\"]'), 13 passed -- predicted-vs-observed match. ECONNREFUSED rose to 4 in this leg (2 real attempts: the original site + the new pin test's own render, both firing with the double off) -- diagnostics increased as expected for an added-test revert, not decreased. Restored via a branch-and-path-scoped git checkout back to the fix commit; git diff HEAD confirmed clean after. Gates: 'pnpm --filter @object-ui/plugin-dashboard type-check' clean (note: script is type-check, not typecheck -- confirmed non-zero-match by reading the echoed command); 'pnpm --filter @object-ui/plugin-dashboard lint' 0 errors, 0 new warnings in the touched file (317 pre-existing warnings elsewhere, unrelated); 'node scripts/check-changeset-presence.mjs' green (empty-frontmatter changeset declared, matching #5280's pattern); 'node scripts/check-changeset-no-major.mjs' green; 'node scripts/check-control-bytes.mjs' green. Note: this repo (objectui) has no scripts/pm/dispatch-gates.mjs -- that script is objectstack/framework-repo tooling; objectui's own AGENTS.md names pnpm lint / pnpm test / root check:* as the wired checks, which is what was run. Dependency-closure build ('pnpm --filter @object-ui/plugin-dashboard^... build') ran clean before type-check per the toolchain-traps note. Final commit: 9e2578265 (branch pushed, draft PR open at that sha).",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions