paperclipai/paperclip · error

Invalid plugin name. Must be lowercase and may include…

Error message

Invalid plugin name. Must be lowercase and may include scope, dots, underscores, or hyphens.

What it means

Argument validation in scaffoldPluginProject: options.pluginName failed isValidPluginName, which enforces a lowercase npm-style name (optionally scoped) with dots, underscores, or hyphens. The name becomes a real npm package name in the generated project, so anything that would be an invalid package identifier is rejected up front.

Solutions

  1. Use a lowercase plugin name containing only letters, digits, dots, underscores, hyphens, and an optional @scope/ prefix.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at packages/plugins/create-paperclip-plugin/src/index.ts:130 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-18). Data as JSON: /api/errors/53732072f9a8912b. Report an issue: GitHub.

Appendix: source

Thrown at packages/plugins/create-paperclip-plugin/src/index.ts:130

  }

  return tarballPath;
}

/**
 * Generate a complete Paperclip plugin starter project.
 *
 * Output includes manifest/worker/UI entries, SDK harness tests, bundler presets,
 * and a local dev server script for hot-reload workflow.
 */
export function scaffoldPluginProject(options: ScaffoldPluginOptions): string {
  const template = options.template ?? "default";
  if (!VALID_TEMPLATES.includes(template)) {
    throw new Error(`Invalid template '${template}'. Expected one of: ${VALID_TEMPLATES.join(", ")}`);
  }

  if (!isValidPluginName(options.pluginName)) {
    throw new Error("Invalid plugin name. Must be lowercase and may include scope, dots, underscores, or hyphens.");
  }

  if (options.category && !VALID_CATEGORIES.has(options.category)) {
    throw new Error(`Invalid category '${options.category}'. Expected one of: ${[...VALID_CATEGORIES].join(", ")}`);
  }

  const outputDir = path.resolve(options.outputDir);
  if (fs.existsSync(outputDir)) {
    throw new Error(`Directory already exists: ${outputDir}`);
  }

  const displayName = options.displayName ?? makeDisplayName(options.pluginName);
  const description = options.description ?? "A Paperclip plugin";
  const author = options.author ?? "Plugin Author";
  const category = options.category ?? (template === "workspace" ? "workspace" : template === "environment" ? "environment" : "connector");
  const manifestId = packageToManifestId(options.pluginName);
  const localSdkPath = path.resolve(options.sdkPath ?? getLocalSdkPackagePath());
  const localSharedPath = getLocalSharedPackagePath(localSdkPath);

View on GitHub (pinned to a7e689b3c3)