keycloak/keycloak · error · Error

Unresolved import: ${warning.exporter}

Error message

Unresolved import: ${warning.exporter}

What it means

Thrown by the custom Rollup onwarn handler in js/themes-vendor/rollup.config.js when Rollup raises an UNRESOLVED_IMPORT warning. The themes-vendor build bundles the React/React-DOM production minified sources; it treats any module specifier that @rollup/plugin-node-resolve cannot locate in node_modules (and that is not declared as external) as fatal. warning.exporter names the exact offending specifier.

Source

Thrown at js/themes-vendor/rollup.config.js:27

  nodeResolve(),
  commonjs({
    strictRequires: "auto",
  }),
  replace({
    preventAssignment: true,
    // React depends on process.env.NODE_ENV to determine which code to include for production.
    // This ensures that no additional code meant for development is included in the build.
    "process.env.NODE_ENV": '"production"',
  }),
  terser(),
];

const targetDir = "target/classes/theme/keycloak/common/resources/vendor";

/** @type{import("rollup").WarningHandlerWithDefault} */
function onwarn(warning, defaultHandler) {
  if (warning.code === "UNRESOLVED_IMPORT") {
    throw new Error(`Unresolved import: ${warning.exporter}`);
  }

  defaultHandler(warning);
}

export default defineConfig([
  {
    input: [
      "node_modules/react/cjs/react.production.min.js",
      "node_modules/react/cjs/react-jsx-runtime.production.min.js",
    ],
    output: {
      dir: path.join(targetDir, "react"),
      format: "es",
    },
    plugins,
    onwarn,
  },

View on GitHub (pinned to 66c7e15a37)

Solutions

  1. Run `npm ci` (or `npm install`) inside js/themes-vendor to fully restore node_modules, then rebuild.
  2. Read the full Rollup diagnostics to find the exact exporter, then confirm js/themes-vendor/node_modules/<exporter> exists.
  3. If the missing specifier is intentionally supplied by the host page or another bundle, add it to that bundle's `external` array in rollup.config.js.
  4. Delete node_modules and package-lock.json, reinstall from the committed lockfile to rule out a corrupted partial install.

Example fix

// before: 'some-peer-lib' is referenced but missing and not declared external
{
  input: "node_modules/react-dom/cjs/react-dom.production.min.js",
  external: ["react"],
}
// after: declare it external so Rollup leaves the import intact
{
  input: "node_modules/react-dom/cjs/react-dom.production.min.js",
  external: ["react", "some-peer-lib"],
}
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from "node:fs";
for (const dep of ["react", "react-dom"]) {
  if (!existsSync(`js/themes-vendor/node_modules/${dep}`)) {
    throw new Error(`Missing dependency '${dep}' -- run: npm ci --prefix js/themes-vendor`);
  }
}

Prevention

When it happens

Trigger: Running the themes-vendor build (npm run build / the Maven frontend goal) when react.production.min.js, react-jsx-runtime.production.min.js, or react-dom.production.min.js pulls in a bare import that is neither present under node_modules nor listed in the bundle's external array.

Common situations: node_modules not installed or only partially restored (npm ci skipped, CI cache miss); a transitive/peer dependency removed by deduping or a version bump; lockfile drift; running the build from a clean checkout without restoring js/themes-vendor/node_modules.

Related errors


AI-assisted analysis of keycloak/keycloak@66c7e15a37 (2026-08-14). Data as JSON: /api/errors/f61ec2a68d7579c2. Report an issue: GitHub.