paperclipai/paperclip · error · Error
Invalid plugin name. Must be lowercase and may include scope
Error message
Invalid plugin name. Must be lowercase and may include scope, dots, underscores, or hyphens.
What it means
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.
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 67001ec6eb)
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.
Example fix
// before
scaffoldPluginProject({ pluginName: 'My Cool Plugin' })
// after
scaffoldPluginProject({ pluginName: 'my-cool-plugin', displayName: 'My Cool Plugin' }) Defensive patterns
Strategy: type-guard
Validate before calling
import { isValidPluginName } from '@paperclip/create-paperclip-plugin';
if (!isValidPluginName(name)) throw new Error('plugin name must be lowercase [a-z0-9._-] or @scope/name'); Type guard
function isValidPluginNameCandidate(name: string): boolean {
return /^@[a-z0-9_-]+\/[a-z0-9._-]+$/.test(name) || /^[a-z0-9._-]+$/.test(name);
} Prevention
- 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.
When it happens
Trigger: 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'.
Common situations: 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.
Related errors
- Invalid template '${template}'. Expected one of: ${VALID_TEM
- Package package.json not found at ${packageJsonPath}
- Packed tarball was not created at ${tarballPath}
- Profile name is required
- Invalid --persona value. Use board or agent.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/53732072f9a8912b.
Report an issue: GitHub.