{"record":{"id":"33603ee94567252e","repo":"paperclipai/paperclip","slug":"invalid-category-options-category-expected-o","errorCode":null,"errorMessage":"Invalid category '${options.category}'. Expected one of: ${[...VALID_CATEGORIES].join(\", \")}","messagePattern":"Invalid category '(.+?)'\\. Expected one of: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugins/create-paperclip-plugin/src/index.ts","lineNumber":134,"sourceCode":"\n/**\n * Generate a complete Paperclip plugin starter project.\n *\n * Output includes manifest/worker/UI entries, SDK harness tests, bundler presets,\n * and a local dev server script for hot-reload workflow.\n */\nexport function scaffoldPluginProject(options: ScaffoldPluginOptions): string {\n  const template = options.template ?? \"default\";\n  if (!VALID_TEMPLATES.includes(template)) {\n    throw new Error(`Invalid template '${template}'. Expected one of: ${VALID_TEMPLATES.join(\", \")}`);\n  }\n\n  if (!isValidPluginName(options.pluginName)) {\n    throw new Error(\"Invalid plugin name. Must be lowercase and may include scope, dots, underscores, or hyphens.\");\n  }\n\n  if (options.category && !VALID_CATEGORIES.has(options.category)) {\n    throw new Error(`Invalid category '${options.category}'. Expected one of: ${[...VALID_CATEGORIES].join(\", \")}`);\n  }\n\n  const outputDir = path.resolve(options.outputDir);\n  if (fs.existsSync(outputDir)) {\n    throw new Error(`Directory already exists: ${outputDir}`);\n  }\n\n  const displayName = options.displayName ?? makeDisplayName(options.pluginName);\n  const description = options.description ?? \"A Paperclip plugin\";\n  const author = options.author ?? \"Plugin Author\";\n  const category = options.category ?? (template === \"workspace\" ? \"workspace\" : template === \"environment\" ? \"environment\" : \"connector\");\n  const manifestId = packageToManifestId(options.pluginName);\n  const localSdkPath = path.resolve(options.sdkPath ?? getLocalSdkPackagePath());\n  const localSharedPath = getLocalSharedPackagePath(localSdkPath);\n  const repoRoot = getRepoRootFromSdkPath(localSdkPath);\n  const useWorkspaceSdk = isInsideDir(outputDir, repoRoot);\n\n  fs.mkdirSync(outputDir, { recursive: true });","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/create-paperclip-plugin/src/index.ts#L116-L152","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Pass one of: connector, workspace, automation, ui, environment (exact lowercase).","Omit category entirely and let it default from the template (workspace -> workspace, environment -> environment, otherwise connector).","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."],"exampleFix":"// before\nscaffoldPluginProject({ pluginName: \"@acme/foo\", outputDir: \"./foo\", category: \"Connectors\" });\n// after\nscaffoldPluginProject({ pluginName: \"@acme/foo\", outputDir: \"./foo\", category: \"connector\" });","handlingStrategy":"validation","validationCode":"import { scaffoldPluginProject } from \"@paperclipai/create-paperclip-plugin\";\nconst VALID_CATEGORIES = new Set([\"connector\", \"workspace\", \"automation\", \"ui\", \"environment\"]]);\nfunction assertCategory(cat: string | undefined): cat is \"connector\" | \"workspace\" | \"automation\" | \"ui\" | \"environment\" {\n  return cat == null || VALID_CATEGORIES.has(cat);\n}\nif (!assertCategory(opts.category)) {\n  throw new Error(`Unsupported category; pick one of: ${[...VALID_CATEGORIES].join(\", \")}`);\n}","typeGuard":"function isPluginCategory(v: unknown): v is \"connector\" | \"workspace\" | \"automation\" | \"ui\" | \"environment\" {\n  return typeof v === \"string\" && [\"connector\",\"workspace\",\"automation\",\"ui\",\"environment\"].includes(v);\n}","tryCatchPattern":null,"preventionTips":["Validate category against the documented set before calling scaffoldPluginProject().","Omit category to use the template-derived default when unsure.","Keep VALID_CATEGORIES in sync with the ScaffoldPluginOptions type."],"tags":["validation","plugin-scaffold","config"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}