vercel/turborepo · error · GeneratorError

plop_unable_to_load_config

plop_unable_to_load_config

Error message

Unable to load generators

What it means

turbo-gen loads your generator config by bundling it with esbuild and handing it to node-plop. createPlopFromConfig returns undefined when node-plop rejects the config, logs the underlying error, and cleans up the bundled file. This GeneratorError with code plop_unable_to_load_config is thrown when that load produced no plop instance.

Source

Thrown at packages/turbo-gen/src/utils/plop.ts:357

export async function runCustomGenerator({
  project,
  generator,
  bypassArgs,
  configPath
}: {
  project: Project;
  generator: Generator;
  bypassArgs?: Array<string>;
  configPath?: string;
}): Promise<void> {
  const resolvedConfigPath = configPath ?? generator.configPath;
  const destBasePath = configPath ?? generator.destBasePath;

  const plop = await createPlopFromConfig(resolvedConfigPath, destBasePath);

  if (!plop) {
    throw new GeneratorError("Unable to load generators", {
      type: "plop_unable_to_load_config"
    });
  }

  let gen: PlopGenerator | undefined;
  try {
    gen = plop.getGenerator(generator.name) as PlopGenerator | undefined;
  } catch {
    // plop throws when generator not found
  }

  if (!gen) {
    throw new GeneratorError(
      `Generator ${qualifiedName(generator)} not found`,
      { type: "plop_generator_not_found" }
    );
  }

View on GitHub (pinned to f9245100cf)

Solutions

  1. Look at the error line logged just above; it is the real load failure from node-plop or esbuild
  2. Make the config export a function: module.exports = function (plop) { ... }
  3. Match the file extension to your package type: use .cjs when "type": "module" is set
  4. Ensure every import in the config resolves from the project

Example fix

// before: config exports an object
module.exports = { generators: [] };
// after: config exports a function that registers generators
module.exports = function (plop) {
  plop.setGenerator("hello", {
    prompts: [],
    actions: [{ type: "add", path: "hello.txt", template: "hi" }]
  });
};
Defensive patterns

Strategy: try-catch

Validate before calling

// smoke-load the config the same way turbo-gen does before running generators
import nodePlop from "node-plop";

const plop = await nodePlop(configPath, { destBasePath: root, force: false });
if (!plop) throw new Error("Unable to load generators");

Type guard

import type { NodePlopAPI } from "node-plop";

function isPlopInstance(value: unknown): value is NodePlopAPI {
  return typeof value === "object" && value !== null && typeof (value as NodePlopAPI).getGenerator === "function";
}

Try / catch

try {
  await runPlopGenerator(args);
} catch (err) {
  if (err instanceof GeneratorError && err.type === "plop_unable_to_load_config") {
    // the real load error was logged above; fix the config export and retry
    console.error("Config failed to load. Ensure it exports a function: module.exports = (plop) => {...}");
    process.exitCode = 1;
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: The config file exists but does not work as a plop config: it does not export a function that receives plop, it throws during evaluation, or it imports something that fails to resolve. nodePlop() rejects, the catch returns undefined, and the caller converts that to this GeneratorError.

Common situations: module.exports = { ... } instead of module.exports = (plop) => { ... }. A plopfile written as ESM default export but loaded as CJS, or the reverse. A syntax error or missing dependency inside the config. TypeScript types stripped incorrectly during bundling.

Related errors


AI-assisted analysis of vercel/turborepo@f9245100cf (2026-08-17). Data as JSON: /api/errors/72c0a32f867d770c. Report an issue: GitHub.