The frontend build fails on main, breaking QA and production deploys (regression from #241) #254

Closed
opened 2026-09-01 09:08:40 -05:00 by bermudalamb · 0 comments
Owner

main does not build. Any Portainer deploy fails with:

failed to deploy a stack: compose build operation failed: failed to solve:
process "/bin/sh -c npm run build" did not complete successfully: exit code: 2

My regression, introduced by #241 and merged in #252. Ten TS2339 errors, all in the e2e specs:

tests/e2e/admin-disable-customer.spec.ts(41,7): error TS2339: Property 'id' does not exist on type '{ email: string; }'.
tests/e2e/admin-inline-category.spec.ts(42,18): error TS2339: Property 'category_name' does not exist on type '{ name: string; }'.
tests/e2e/email-templates.spec.ts(59,18): error TS2339: Property 'subject' does not exist on type '{ key: string; }'.
tests/e2e/favorites-filter.spec.ts(187,31): error TS2339: Property 'id' does not exist on type '{ name: string; }'.
…

Cause. findOrFail<T>(items: T[], predicate: (item: T) => boolean, …) infers T from both parameters. The call sites annotate the predicate as documentation — (c: { email: string }) => … — and the arrays come from .json(), which is any and offers no competing inference candidate. So T became the one-field shape written in the lambda, and every caller then failed on the field it actually wanted. Array.prototype.find has no such problem, which is why the code this replaced type-checked fine.

Why I did not catch it. I verified with a bare npx tsc --noEmit, which uses tsconfig.json — and that config is "include": ["src"]. It structurally cannot see tests/. The specs are type-checked by the second command in npm run build, tsc -p tsconfig.test.json --noEmit, which is exactly the step the Docker build runs and the step that fails. I ran a command that could not fail on the files I had changed, and reported the result as verification.

Fix. Type the four .json() responses at their call sites and drop the now-redundant predicate annotations, so T is inferred from real data rather than from a lambda. findOrFail also takes NoInfer<T> on the predicate so a stray annotation can never drive the element type again.

Verified with npm run build — the command the container actually runs — plus lint, the unit suite, and two consecutive full e2e passes.

`main` does not build. Any Portainer deploy fails with: ``` failed to deploy a stack: compose build operation failed: failed to solve: process "/bin/sh -c npm run build" did not complete successfully: exit code: 2 ``` My regression, introduced by #241 and merged in #252. Ten `TS2339` errors, all in the e2e specs: ``` tests/e2e/admin-disable-customer.spec.ts(41,7): error TS2339: Property 'id' does not exist on type '{ email: string; }'. tests/e2e/admin-inline-category.spec.ts(42,18): error TS2339: Property 'category_name' does not exist on type '{ name: string; }'. tests/e2e/email-templates.spec.ts(59,18): error TS2339: Property 'subject' does not exist on type '{ key: string; }'. tests/e2e/favorites-filter.spec.ts(187,31): error TS2339: Property 'id' does not exist on type '{ name: string; }'. … ``` **Cause.** `findOrFail<T>(items: T[], predicate: (item: T) => boolean, …)` infers `T` from both parameters. The call sites annotate the predicate as documentation — `(c: { email: string }) => …` — and the arrays come from `.json()`, which is `any` and offers no competing inference candidate. So `T` became the one-field shape written in the lambda, and every caller then failed on the field it actually wanted. `Array.prototype.find` has no such problem, which is why the code this replaced type-checked fine. **Why I did not catch it.** I verified with a bare `npx tsc --noEmit`, which uses `tsconfig.json` — and that config is `"include": ["src"]`. It structurally cannot see `tests/`. The specs are type-checked by the second command in `npm run build`, `tsc -p tsconfig.test.json --noEmit`, which is exactly the step the Docker build runs and the step that fails. I ran a command that could not fail on the files I had changed, and reported the result as verification. **Fix.** Type the four `.json()` responses at their call sites and drop the now-redundant predicate annotations, so `T` is inferred from real data rather than from a lambda. `findOrFail` also takes `NoInfer<T>` on the predicate so a stray annotation can never drive the element type again. Verified with `npm run build` — the command the container actually runs — plus lint, the unit suite, and two consecutive full e2e passes.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bermudalamb/redefined-designs#254