How to Fix: Next 14.2.12 with react-pdf and pdfjs-dist | Build fails with webpack error: TypeError: Promise.withResolvers is not a function | Passes Vercel build with swcMinify: false

6 min read

Next 14.2.12 + react-pdf build failure: fixing Promise.withResolvers is not a function

This bug looks misleading because the app may work in one environment and fail in another, but the failure has a very specific cause: pdfjs-dist is pulling in code that expects a newer JavaScript runtime feature, while your Next.js 14.2.12 Webpack build path is evaluating that code in an environment where Promise.withResolvers does not exist.

Understanding the Root Cause

The error TypeError: Promise.withResolvers is not a function usually appears when react-pdf and pdfjs-dist resolve to a build of PDF.js that assumes support for a newer ECMAScript API.

Promise.withResolvers is a relatively new JavaScript feature. If the version of Node.js, the bundling pipeline, or the evaluated dependency output does not support it, the build breaks before your page can render.

In this case, the problem is commonly triggered by the interaction between:

  • Next.js 14.2.12
  • react-pdf
  • pdfjs-dist version selection
  • Webpack minification/transformation during build

The clue from the issue is important: the build passes when swcMinify: false is set. That means the failure is not just about your component code. It points to a dependency-processing mismatch in the production build pipeline. In practice, one of the imported PDF.js bundles is being processed in a way that exposes the unsupported Promise.withResolvers call.

There are three common technical reasons this happens:

  1. pdfjs-dist is too new for the runtime/build combination used by your Next.js app.
  2. react-pdf is importing a PDF.js entry that is not ideal for your current bundler setup.
  3. SWC minification or related build optimization changes how that dependency is parsed or executed, which is why disabling it appears to “fix” the issue.

The most reliable fix is to make the PDF.js dependency chain deterministic and use a version combination known to work with Next 14.

Step-by-Step Solution

The safest production-ready approach is:

  1. Use compatible versions of react-pdf and pdfjs-dist.
  2. Configure the PDF worker explicitly.
  3. If needed, pin pdfjs-dist to a version that does not rely on Promise.withResolvers in your build path.
  4. Keep swcMinify enabled unless a temporary workaround is required.

1. Install compatible package versions

First, check what you currently have installed:

npm ls react-pdf pdfjs-dist next

If your dependency tree pulls a newer pdfjs-dist release, pin it explicitly. A common stable path is to align versions so react-pdf does not float to an incompatible PDF.js build.

npm install react-pdf pdfjs-dist@3.11.174

If you use Yarn:

yarn add react-pdf pdfjs-dist@3.11.174

If you use pnpm:

pnpm add react-pdf pdfjs-dist@3.11.174

Then remove existing lock artifacts if the wrong subdependency keeps getting reused:

rm -rf node_modules package-lock.json .next
npm install

For Yarn:

rm -rf node_modules yarn.lock .next
yarn install

2. Configure the PDF worker correctly

In your PDF component, explicitly set the worker source. This prevents PDF.js from resolving the wrong worker entry at runtime.

'use client';

import { pdfjs, Document, Page } from 'react-pdf';
import 'react-pdf/dist/Page/AnnotationLayer.css';
import 'react-pdf/dist/Page/TextLayer.css';

pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  'pdfjs-dist/build/pdf.worker.min.js',
  import.meta.url
).toString();

export default function PdfViewer() {
  return (
    <Document file="/sample.pdf">
      <Page pageNumber={1} />
    </Document>
  );
}

If your project uses the App Router, keep the PDF viewer in a client component. react-pdf depends on browser APIs and should not be rendered on the server.

3. Force a safe pdfjs-dist version with overrides or resolutions

If another package pulls in a conflicting version, lock it at the package manager level.

For npm:

{
  "overrides": {
    "pdfjs-dist": "3.11.174"
  }
}

For Yarn:

{
  "resolutions": {
    "pdfjs-dist": "3.11.174"
  }
}

Then reinstall dependencies:

rm -rf node_modules package-lock.json yarn.lock .next
npm install

4. Keep Next.js config clean

Use a minimal next.config.js unless you have a strong reason to customize Webpack.

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
};

module.exports = nextConfig;

If your project only builds successfully with swcMinify: false, treat that as a temporary workaround, not the final fix.

/** @type {import('next').NextConfig} */
const nextConfig = {
  swcMinify: false,
};

module.exports = nextConfig;

This setting can unblock deployment, but it does not address the real incompatibility. The better long-term fix is version alignment.

5. Ensure the PDF component is client-only

If you are importing the viewer directly into a server component, wrap it with a dynamic import and disable SSR.

import dynamic from 'next/dynamic';

const PdfViewer = dynamic(() => import('./PdfViewer'), {
  ssr: false,
});

export default function Page() {
  return <PdfViewer />;
}

This avoids server-side evaluation of browser-specific PDF logic.

6. Verify the fix

npm run dev
npm run build

If the build now passes with normal settings, the dependency mismatch is resolved.

For most affected projects, this combination is the practical fix:

  • Next.js 14.2.12
  • react-pdf installed normally
  • pdfjs-dist pinned to 3.11.174
  • client-only PDF viewer
  • explicit workerSrc configuration

Common Edge Cases

1. The error still appears after downgrading pdfjs-dist

Your lockfile may still resolve multiple versions. Run:

npm ls pdfjs-dist

If more than one version appears, use overrides or reinstall from a clean state.

2. The app works in dev but fails only in production

This usually means minification, tree-shaking, or a different module path is involved during next build. That is why production verification is essential after changing package versions.

3. The PDF worker fails to load

If the main error disappears but the PDF does not render, the worker path may be wrong. Confirm that pdfjs.GlobalWorkerOptions.workerSrc points to a valid bundled asset.

Once the dependency issue is fixed, you may hit browser-only API problems such as window is not defined. That means the PDF component is still being evaluated on the server and should be loaded with ssr: false.

5. Vercel succeeds but local builds fail

This often happens when local Node.js differs from the deployment runtime, or when the local cache contains stale modules. Match your Node version and clear the install state before retesting.

FAQ

Why does setting swcMinify: false make the build pass?

Because it changes how Next.js processes dependency code during production build. It avoids the exact path that surfaces the incompatible Promise.withResolvers usage, but it is a workaround rather than the best fix.

Should I upgrade Next.js, react-pdf, or pdfjs-dist?

Start by aligning react-pdf with a known working pdfjs-dist version. If you want to upgrade later, do it intentionally and verify both dev and production builds.

Can I polyfill Promise.withResolvers instead?

You can, but it is usually not the right solution here. This problem is better solved by using a compatible PDF.js build path rather than patching a runtime feature for a dependency that should not require it in your current stack.

The shortest reliable fix for this GitHub issue is to pin pdfjs-dist to a compatible version, keep the viewer client-side only, and configure the PDF worker explicitly. If disabling swcMinify is the only thing that works, use it only as a temporary deployment escape hatch while you clean up the dependency graph.

For the original reproduction, review the linked sample repository and test the version-pinning approach first, since that is the most direct fix for this class of Next.js + react-pdf + pdfjs-dist build failures.

Leave a Reply

Your email address will not be published. Required fields are marked *