{"record":{"id":"53732072f9a8912b","repo":"paperclipai/paperclip","slug":"invalid-plugin-name-must-be-lowercase-and-may-inc","errorCode":null,"errorMessage":"Invalid plugin name. Must be lowercase and may include scope, dots, underscores, or hyphens.","messagePattern":"Invalid plugin name\\. Must be lowercase and may include scope, dots, underscores, or hyphens\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugins/create-paperclip-plugin/src/index.ts","lineNumber":130,"sourceCode":"  }\n\n  return tarballPath;\n}\n\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);","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/create-paperclip-plugin/src/index.ts#L112-L148","documentation":"scaffoldPluginProject validates options.pluginName with isValidPluginName, which requires either an unscoped lowercase name matching /^[a-z0-9._-]+$/ or a scoped name matching /^@[a-z0-9_-]+\\/[a-z0-9._-]+$/. Uppercase, spaces, slashes in the wrong place, or other punctuation are rejected.","triggerScenarios":"Passing a plugin name with uppercase letters, spaces, leading '@' without a slash, multiple slashes, or characters outside [a-z0-9._-]. Examples that fail: 'MyPlugin', 'foo bar', '@Scope/Foo', 'foo+v2', 'foo/bar'.","commonSituations":"User supplies a human-readable display name where the package name is expected; mixed-case org/scope; illegal npm characters copied from a non-npm context.","solutions":["Lowercase the name and restrict to letters, digits, '.', '_', '-'.","For a scoped plugin use the form '@scope/name' with both halves lowercase.","Set the human-readable name via options.displayName instead of pluginName."],"exampleFix":"// before\nscaffoldPluginProject({ pluginName: 'My Cool Plugin' })\n// after\nscaffoldPluginProject({ pluginName: 'my-cool-plugin', displayName: 'My Cool Plugin' })","handlingStrategy":"type-guard","validationCode":"import { isValidPluginName } from '@paperclip/create-paperclip-plugin';\nif (!isValidPluginName(name)) throw new Error('plugin name must be lowercase [a-z0-9._-] or @scope/name');","typeGuard":"function isValidPluginNameCandidate(name: string): boolean {\n  return /^@[a-z0-9_-]+\\/[a-z0-9._-]+$/.test(name) || /^[a-z0-9._-]+$/.test(name);\n}","tryCatchPattern":null,"preventionTips":["Use lowercase ASCII only; put display text in displayName, not pluginName.","For scoped packages, follow @scope/name with both halves lowercase.","Validate with isValidPluginName before prompting the user to confirm a name."],"tags":["input-validation","naming","scaffolding","create-paperclip-plugin"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}