Skip to content
Latchkey

esbuild "Transform failed with N errors" - Fix in CI

esbuild tried to transform a file and could not. The message names the file, line, and a specific syntax error - JSX fed to a non-JSX loader, a real parse error, or a syntax the configured target rejects.

What this error means

A build using esbuild (directly, or via Vite/tsup) fails with Transform failed with N errors followed by ERROR: <file>:<line>: .... It is deterministic and points at the exact location.

esbuild
✘ [ERROR] Transform failed with 1 error:
src/components/Card.tsx:14:2: ERROR: Expected ">" but found "className"
    at failureErrorWithLog (/app/node_modules/esbuild/lib/main.js:1649:15)

Diagnose it: is it resolution, transform, or memory?

Bundler failures in CI fall into three families and the error text often points at the wrong one. A module that resolves on your machine and not on the runner is nearly always case sensitivity or a missing optional dependency; a transform error is a config or version mismatch; and an unexplained kill with no stack is the out-of-memory reaper, not a build error at all.

Terminal
# 1. resolution: does the file exist with EXACTLY that case?
git ls-files | grep -i "the/imported/path"

# 2. transform: what versions is CI actually resolving?
npm ls webpack vite rollup esbuild typescript 2>/dev/null | head -20

# 3. memory: was it killed rather than failed?
#    exit 137 = SIGKILL (OOM). Nothing in the bundler log will explain it.
node --max-old-space-size=4096 node_modules/.bin/vite build

Common causes

JSX handled by the wrong loader

JSX in a .ts file (instead of .tsx), or a loader: 'ts' where JSX appears, makes esbuild parse < as an operator and fail.

Genuine syntax error

A stray token, unclosed brace, or invalid construct in the source - a real error esbuild reports at the exact line/column.

Syntax newer than the target

A target set too low (e.g. es2015) can reject or fail to transform syntax the source uses.

How to fix it

Fix the loader/extension or syntax

  1. Put JSX in .tsx/.jsx, or set the esbuild loader to tsx/jsx for the file.
  2. Open the reported line and correct the actual syntax error.
  3. Confirm the file also type-checks with tsc --noEmit.

Set an appropriate target/loader in config

esbuild config
// esbuild config
{ loader: { '.ts': 'tsx' }, jsx: 'automatic', target: 'es2020' }

Make the build reproducible before you debug it

  • Pin the Node major in setup-node and in engines. A bundler that resolves native bindings will pick a different prebuilt binary across majors.
  • Delete node_modules locally and reinstall from the lockfile before concluding the runner is at fault; most "works locally" reports are stale local state.
  • Set CI=true locally to reproduce. Several toolchains change behaviour under it, including treating warnings as errors.
  • Exit code 137 is an out-of-memory kill. Raise --max-old-space-size or move to a larger runner rather than searching the bundler config.

How to prevent it

  • Keep JSX in .tsx/.jsx so esbuild selects the JSX loader.
  • Set a target that matches the syntax your source uses.
  • Type-check in CI so syntax errors surface before the transform.

Frequently asked questions

What causes esbuild "Transform failed with N errors"?
There are 3 common causes: jsx handled by the wrong loader, genuine syntax error, and syntax newer than the target. JSX in a .ts file (instead of .tsx), or a loader: 'ts' where JSX appears, makes esbuild parse < as an operator and fail.
How do I fix esbuild "Transform failed with N errors"?
There are 2 fixes depending on which cause you have: fix the loader/extension or syntax and set an appropriate target/loader in config. Work through them in order, since the first is the most common.
What does esbuild "Transform failed with N errors" actually mean?
A build using esbuild (directly, or via Vite/tsup) fails with Transform failed with N errors followed by ERROR: <file>:<line>: ....
How do I stop esbuild "Transform failed with N errors" happening again?
Keep JSX in .tsx/.jsx so esbuild selects the JSX loader. The prevention section lists 3 changes that keep it from recurring.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card