TypeError: Client is not a constructor

Node.js · updated 2026-11-04

Thrown at the new expression when the value isn't a constructor: an object (often a module namespace), undefined, an arrow function or a plain value. In builds that transpile imports, the message shows the generated name, such as _client.default is not a constructor, which points at the import line rather than the class.

TypeError: _sdk.default is not a constructor
    at createClient (/app/dist/services/payments.js:12:18)
    at Object.<anonymous> (/app/dist/server.js:8:16)

Quick fix

Log the imported value (console.log(typeof X, X)) at the failing line. If it's an object with a default or a named export inside, change the import: import { Client } from 'pkg' or import pkg from 'pkg' then new pkg.Client(), matching what the package exports. With CommonJS, require('pkg').default or a named property may be what you need. If it's undefined, look for a circular import.

  1. Print typeof and the value of the imported name right before the new call.
  2. Check the package README or its types for whether the class is a default export or a named export.
  3. Fix the import to match: default (import X from), named (import { X } from) or namespace (import * as m; new m.X()).
  4. In TypeScript compiled to CommonJS, turn on esModuleInterop so default imports of CommonJS packages work.
  5. If the value is undefined only at startup, two modules import each other: move the shared class to its own file.
typescript
// The package exports the class by name, not as default
// import Client from 'some-sdk';          // Client is the module object here
import { Client } from 'some-sdk';

const client = new Client({ apiKey: process.env.SDK_KEY });

// CommonJS: pick the right property
// const Client = require('some-sdk');      // { Client: [class], default: ... }
const { Client: CjsClient } = require('some-sdk');

Why it happens

Default vs named import

The package exports the class as a named export (or under default), and the import takes the other form, so the value is the module object or undefined.

ESM and CommonJS interop

Importing a CommonJS package from ESM gives you module.exports as the default; requiring an ESM-compiled package from CommonJS puts the class under .default. Bundlers and TypeScript settings (esModuleInterop) change which one you get.

Circular import

Two modules import each other, and one runs before the other finished, so the class is still undefined when new runs. "Class extends value undefined is not a constructor or null" is the same cause.

Not a class at all

Arrow functions, async functions and plain objects cannot be called with new; a library may expose a factory (createClient()) instead of a class.

Other fixes

  • After upgrading a package, check its changelog: moving from a default export to named exports is a common breaking change.
  • node --trace-uncaught or source maps in production show the original import line instead of the transpiled _x.default name.

Same error, other wording

  • TypeError: _sdk.default is not a constructor
  • TypeError: Class extends value undefined is not a constructor or null
  • TypeError: (intermediate value) is not a constructor

Let your coding agent catch the next one

Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:

> Find the "is not a constructor" errors in production, check what the import at that line resolves to (default, named or namespace), and fix the import to match what the package exports.

Plans from $29/moSee what your agent readsSee the setupCancel any time from the billing portal

Related errors

More in Undefined, None and type errors

References: MDN: TypeError "x" is not a constructor, Node.js docs: ECMAScript modules (CommonJS interop), TypeScript TSConfig reference: esModuleInterop