Skip to content

ineffective-dynamic-import-ledger's closeBundle counter-probe replaces the real error whenever an earlier console plugin fails the build #6093

Description

@yinlianghui-tw

Found while reproducing #5996 (the eager-closure ENOENT). Not caused by that card and not fixed there — filing so triage can rank it.

What I measured

scripts/vite-ineffective-dynamic-imports.ts ends with a counter-probe in closeBundle: if none of the 43 pinned INEFFECTIVE_DYNAMIC_IMPORT warnings fired, it errors. The probe is well-motivated — its own message says so: "or this build never got far enough to emit them, in which case the number to distrust is the zero, not the list."

The problem is what happens to the other error. closeBundle runs even when the build has already failed, and the error it throws supersedes the aggregated build error in vite build's output. The real cause is not appended, not printed above, not present anywhere in the log — it is gone.

Measured on apps/console, vite@8.2.1 + rolldown@1.2.3, base 7c96c9420, by making emit-eager-closure-report's writeBundle fail (an out-of-tree OBJECTSTACK_CLIENT_DIST override whose own dependencies do not resolve — see the sibling card).

With the full plugin list — the only thing the developer sees:

error during build:
Error [RolldownError]: 43 pinned ineffective dynamic import(s) did NOT fire. Either they were fixed
— delete them from `DEFEATED_LAZY_FIELD_WIDGETS` in `scripts/vite-ineffective-dynamic-imports.ts`
and record the win in the PR — or this build never got far enough to emit them, in which case the
number to distrust is the zero, not the list.
- packages/fields/src/widgets/AddressField.tsx
… 42 more lines …

grep -c ENOENT on that log: 0. The actual failure is invisible.

Same build, same override, that one plugin removed from the array:

error during build:
Build failed with 1 error:
[plugin emit-eager-closure-report]
Error: ENOENT: no such file or directory, open '.../apps/console/dist/@objectstack/core/logger'

Why it is worth a line

This is generic, not specific to the plugin I happened to be debugging: any console build that dies before the pinned warnings are emitted reports the ledger's counter-probe instead of its own cause, and hands the developer a 45-line list of field widgets that have nothing to do with the failure. The 43 did NOT fire message reads as a ledger drift, so the first instinct is to go edit DEFEATED_LAZY_FIELD_WIDGETS — which is exactly the wrong move and would break the ledger for real.

This also blunts work that lands elsewhere: PR for #5996 replaces that ENOENT with a self-diagnosing message naming the unresolved import, and under the real plugin stack that message is masked too — zero occurrences in the log, before and after. The improvement is correct but invisible until this is handled.

Possible shapes (not a recommendation)

  • Have the counter-probe stand down when the build has already errored — the condition its own message already describes ("this build never got far enough"). Detecting that from closeBundle needs a flag set by a buildEnd/renderError hook, since the probe cannot otherwise tell "zero because fixed" from "zero because dead".
  • Or keep it unconditional but make it non-masking: emit as a warning when a prior error is known, so the real error still reaches the top.
  • Either way the pinned-drift signal the probe exists for must survive on a successful build, which is the case it was written for.

Related: #5325 (the ledger), #5996 (where this was found).

Metadata

Metadata

Labels

bugSomething isn't workingdomain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repopm:dispatched

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions