#4520·esbuild

[Bug]: generated `var` from object-rest lowering collides with an existing module variable when bundling

Author: axdanbolCreated Aug 20, 2026Updated Aug 20, 2026

See this bug for yourself here: esbuild playground reproduction

This appears related to #4471, which was fixed in esbuild 0.28.1. However, the collision still occurs in esbuild 0.28.2 when one of the conflicting var declarations is generated by esbuild while lowering object-rest syntax.

Give the following three modules:

entry.js:

javascript
import { C } from './moduleA.js';
import { rest } from './moduleB.js';

console.log(C.make(), rest);

moduleA.js:

javascript
var _a;
export class C {
  static make() {
    return new _a();
  }
}
_a = C;

moduleB.js:

javascript
const value = { a: 1, b: 2 };
export const { a, ...rest } = value;

And then bundle them with this command:

esbuild entry.js --bundle --supported:object-rest-spread=false

Output:

javascript
(() => {
  // ... spread helpers omitted for clarity

  // moduleA.js
  var _a;
  var C = class {
    static make() {
      return new _a();
    }
  };
  _a = C;

  // moduleB.js
  var value = { a: 1, b: 2 };
  var _a = value, { a } = _a, rest = __objRest(_a, ["a"]);

  // entry.js
  console.log(C.make(), rest);
})();

Notice how the object rest spread has created a temporary variable _a in moduleB.js which conflicts with the identically named variable in moduleA.js. Calling C.make() then results in TypeError: _a is not a constructor as _a has been overwritten. The expected behavior is that the _a variable in moduleB.js would be given a different unique name.

For a little context, the pattern in moduleA.js is sometimes produced by TypeScript/ng-packagr when compiling self-referential classes. Minification seems to mask the collision by renaming the bindings.