vercel/turborepo · error · GeneratorError

plop_error_running_generator

plop_error_running_generator

Error message

Failed to run generator

What it means

The turbo-gen custom generator wraps plop to run your plopfile. It lets GeneratorError instances pass through untouched. It wraps every other error from prompts or actions in a GeneratorError with code plop_error_running_generator and the original message. The error means the plopfile threw, not that a configured action merely reported failure.

Source

Thrown at packages/turbo-gen/src/generators/custom.ts:88

    await runCustomGenerator({
      project,
      generator: selectedGenerator,
      bypassArgs: opts.args,
      configPath: opts.config
    });
  } catch (err) {
    // pass any GeneratorErrors through to root
    if (err instanceof GeneratorError) {
      throw err;
    }

    // capture any other errors and throw as GeneratorErrors
    let message = "Failed to run generator";
    if (err instanceof Error) {
      message = err.message;
    }

    throw new GeneratorError(message, {
      type: "plop_error_running_generator"
    });
  } finally {
    if (isOnboarding) {
      logger.log();
      logger.info(`Congrats! You just ran your first Turborepo generator`);
      logger.dimmed(
        "Learn more about custom Turborepo generators - https://turborepo.dev/docs/guides/generating-code#custom-generators"
      );
    }
  }

  logger.log();
  logger.bold(logger.turboGradient(">>> Success!"));
}

View on GitHub (pinned to f9245100cf)

Solutions

  1. Read the message inside the GeneratorError; it carries the original error text
  2. Open the plopfile named in the generator output and fix the throwing line
  3. Verify every setHelper, setPartial, and setGenerator call matches what actions reference
  4. Run the plopfile standalone with npx plop in the same directory to reproduce the failure faster

Example fix

// before: plopfile uses an unregistered helper
module.exports = function (plop) {
  plop.setGenerator("widget", {
    prompts: [],
    actions: [{ type: "add", path: "src/{{ PascalName }}.ts", templateFile: "tpl.hbs" }]
  });
};
// after: register the helper used by the template
module.exports = function (plop) {
  plop.setHelper("PascalName", (s) => s.charAt(0).toUpperCase() + s.slice(1));
  plop.setGenerator("widget", {
    prompts: [],
    actions: [{ type: "add", path: "src/{{ PascalName name }}.ts", templateFile: "tpl.hbs" }]
  });
};
Defensive patterns

Strategy: try-catch

Type guard

import { GeneratorError } from "turbo-gen"; // or your local GeneratorError type

function isGeneratorError(err: unknown): err is GeneratorError {
  return err instanceof Error && "type" in err && typeof (err as GeneratorError).type === "string";
}

Try / catch

try {
  await runGenerator();
} catch (err) {
  if (err instanceof GeneratorError && err.type === "plop_error_running_generator") {
    // err.message carries the underlying plopfile error; log and stop
    console.error(`generator failed: ${err.message}`);
    process.exitCode = 1;
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: The plopfile throws during runPrompts or runActions: an invalid action type, a missing helper or partial registered at load time, a template compile error, or any runtime throw in your own action code. The catch converts the thrown value to a GeneratorError, keeping the message when err instanceof Error.

Common situations: A plopfile references a handlebars helper that is not registered. An action uses type "add" with a template path outside basePath. A custom action function throws. TypeScript or import errors inside the plopfile surface here.

Related errors


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