{"record":{"id":"3e538cb0c3bd62c2","repo":"yarnpkg/yarn","slug":"scope-should-not-be-empty-got-str","errorCode":null,"errorMessage":"Scope should not be empty, got \"${str}\"","messagePattern":"Scope should not be empty, got \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/commands/create.js","lineNumber":31,"sourceCode":"export function setFlags(commander: Object) {\n  commander.description('Creates new projects from any create-* starter kits.');\n}\n\nexport function hasWrapper(commander: Object, args: Array<string>): boolean {\n  return true;\n}\n\nexport function parsePackageName(str: string): Object {\n  if (str.charAt(0) === '/') {\n    throw new Error(`Name should not start with \"/\", got \"${str}\"`);\n  }\n  if (str.charAt(0) === '.') {\n    throw new Error(`Name should not start with \".\", got \"${str}\"`);\n  }\n  const parts = str.split('/');\n  const isScoped = str.charAt(0) === '@';\n  if (isScoped && parts[0] === '@') {\n    throw new Error(`Scope should not be empty, got \"${str}\"`);\n  }\n  const scope = isScoped ? parts[0] : '';\n  const name = parts[isScoped ? 1 : 0] || '';\n  const path = parts.slice(isScoped ? 2 : 1).join('/');\n  const fullName = [scope, name].filter(Boolean).join('/');\n  const full = [scope, name, path].filter(Boolean).join('/');\n\n  return {fullName, name, scope, path, full};\n}\n\nexport function coerceCreatePackageName(str: string): Object {\n  const pkgNameObj = parsePackageName(str);\n  const coercedName = pkgNameObj.name !== '' ? `create-${pkgNameObj.name}` : `create`;\n  const coercedPkgNameObj = {\n    ...pkgNameObj,\n    name: coercedName,\n    fullName: [pkgNameObj.scope, coercedName].filter(Boolean).join('/'),\n    full: [pkgNameObj.scope, coercedName, pkgNameObj.path].filter(Boolean).join('/'),","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/yarnpkg/yarn/blob/c2dda503f3759b5be5f0e24ecd9cf5c97a540147/src/cli/commands/create.js#L13-L49","documentation":"`parsePackageName` treats a leading `@` as a scoped package and splits on `/`. At `create.js:31`, if the first segment is exactly `@` (i.e. the input is `@` or starts with `@/...`), the scope is empty and the name is rejected as 'Scope should not be empty'. This mirrors npm's rule that `@scope/name` requires a non-empty scope.","triggerScenarios":"`isScoped && parts[0] === '@'`, e.g. inputs `@`, `@/foo`, `@/`. Common when a TypeScript path-alias style (`@/...`) or an Angular/Nest convention leaks into the create argument.","commonSituations":"Copy-pasting a scoped import alias (`@/components`) as the kit name, or forgetting to type the scope after `@`.","solutions":["Provide a real scope and name: `yarn create @scope/name` (e.g. `yarn create @nestjs/new`)","For an unscoped kit, drop the `@` entirely: `yarn create react-app`."],"exampleFix":"// before\n$ yarn create @/my-kit\n\n// after\n$ yarn create @my-org/my-kit","handlingStrategy":"validation","validationCode":"function assertScopedNameWellFormed(str: string): void {\n  const parts = str.split('/');\n  if (str.charAt(0) === '@' && parts[0] === '@') {\n    throw new Error(`Scoped name has empty scope: '${str}'. Use '@scope/name'.`);\n  }\n}","typeGuard":"function isValidScopedName(s: string): boolean {\n  if (s.charAt(0) !== '@') return true;\n  const parts = s.split('/');\n  return parts.length >= 2 && parts[0].length > 1 && parts[1].length > 0;\n}","tryCatchPattern":null,"preventionTips":["Validate scoped inputs with a name regex (e.g. `^@?[a-z0-9][\\w-.]*(/[a-z0-9][\\w-.]*)?$`) before passing to create."],"tags":["yarn-create","validation","scoped-package"],"backgroundTag":null,"analyzedSha":"c2dda503f3759b5be5f0e24ecd9cf5c97a540147","analyzedAt":"2026-08-13T04:17:06.305Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}