paperclipai/paperclip · error · Error

Invalid category '${options.category}'. Expected one of: ${[

Error message

Invalid category '${options.category}'. Expected one of: ${[...VALID_CATEGORIES].join(", ")}

What it means

Thrown by scaffoldPluginProject() when options.category is supplied but is not one of the allowed plugin categories. VALID_CATEGORIES is the set connector, workspace, automation, ui, environment (defined at packages/plugins/create-paperclip-plugin/src/index.ts:8). The check is skipped when category is omitted, in which case a default is derived from the chosen template.

Source

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

/**
 * 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);
  const repoRoot = getRepoRootFromSdkPath(localSdkPath);
  const useWorkspaceSdk = isInsideDir(outputDir, repoRoot);

  fs.mkdirSync(outputDir, { recursive: true });

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Pass one of: connector, workspace, automation, ui, environment (exact lowercase).
  2. Omit category entirely and let it default from the template (workspace -> workspace, environment -> environment, otherwise connector).
  3. If you need a new category, add it to VALID_CATEGORIES in packages/plugins/create-paperclip-plugin/src/index.ts:8 and update the ScaffoldPluginOptions type at line 17 before scaffolding.

Example fix

// before
scaffoldPluginProject({ pluginName: "@acme/foo", outputDir: "./foo", category: "Connectors" });
// after
scaffoldPluginProject({ pluginName: "@acme/foo", outputDir: "./foo", category: "connector" });
Defensive patterns

Strategy: validation

Validate before calling

import { scaffoldPluginProject } from "@paperclipai/create-paperclip-plugin";
const VALID_CATEGORIES = new Set(["connector", "workspace", "automation", "ui", "environment"]]);
function assertCategory(cat: string | undefined): cat is "connector" | "workspace" | "automation" | "ui" | "environment" {
  return cat == null || VALID_CATEGORIES.has(cat);
}
if (!assertCategory(opts.category)) {
  throw new Error(`Unsupported category; pick one of: ${[...VALID_CATEGORIES].join(", ")}`);
}

Type guard

function isPluginCategory(v: unknown): v is "connector" | "workspace" | "automation" | "ui" | "environment" {
  return typeof v === "string" && ["connector","workspace","automation","ui","environment"].includes(v);
}

Prevention

When it happens

Trigger: Calling scaffoldPluginProject({ pluginName, outputDir, category: "data" }) or any category string outside the allowed set. Also triggered by passing a pluralized or misspelled value like "connectors", "UI", or "Automation" (case-sensitive — only lowercase values match).

Common situations: Typos and casing mistakes (e.g. "Connectors", "UI"). Assuming a category exists because it is a valid template name (template "default" has no matching category). Copy-pasting a category from an older plugin version after the catalog changed.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/33603ee94567252e. Report an issue: GitHub.