{"record":{"id":"e3296f36ac2a2243","repo":"slidevjs/slidev","slug":"invalid-type-name-name-only-valid-npm-pac","errorCode":null,"errorMessage":"Invalid ${type} name \"${name}\". Only valid npm package names are allowed.","messagePattern":"Invalid (.+?) name \"(.+?)\"\\. Only valid npm package names are allowed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/slidev/node/resolver.ts","lineNumber":345,"sourceCode":"  }\n\n  return async function (name: string, importer: string): Promise<[name: string, root: string | null]> {\n    const { userRoot } = await getRoots()\n\n    if (name === 'none')\n      return ['', null]\n\n    // local path\n    if (name[0] === '/')\n      return [name, name]\n    if (name.startsWith('@/'))\n      return [name, resolve(userRoot, name.slice(2))]\n    if (name[0] === '.' || (name[0] !== '@' && name.includes('/')))\n      return [name, resolve(dirname(importer), name)]\n\n    // Validate that the name is a safe npm package name before resolving\n    if (!RE_SAFE_PKG_NAME.test(name))\n      throw new Error(`Invalid ${type} name \"${name}\". Only valid npm package names are allowed.`)\n\n    // search for local packages first\n    {\n      const possiblePkgNames = [name]\n\n      if (!name.includes('/') && !name.startsWith('@')) {\n        possiblePkgNames.unshift(\n          `@slidev/${type}-${name}`,\n          `slidev-${type}-${name}`,\n        )\n      }\n\n      for (const pkgName of possiblePkgNames) {\n        const pkgRoot = await findPkgRoot(pkgName, importer)\n        if (pkgRoot)\n          return [pkgName, pkgRoot]\n      }\n    }","sourceCodeStart":327,"sourceCodeEnd":363,"githubUrl":"https://github.com/slidevjs/slidev/blob/0d798ace5828966d9f77f62094d5f7a971ad98f7/packages/slidev/node/resolver.ts#L327-L363","documentation":"Thrown by the theme/addon resolver returned from createResolver when the supplied name fails RE_SAFE_PKG_NAME (/^(?:@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/). This guards the resolution branch that treats the name as an npm package name, after local-path forms (/, @/, ./, foo/bar) are excluded.","triggerScenarios":"Configuring theme/addon with a name containing uppercase letters, spaces, or other characters disallowed by npm naming rules, and not matching any local-path prefix. E.g. theme: 'My Theme', addon: 'foo!bar', or theme: 'A'.","commonSituations":"Typo in the headmatter theme: value; using a display name instead of the package name; copy-pasting a theme's human title rather than its npm name; trailing whitespace or non-ASCII characters.","solutions":["Use the package's npm name (lowercase, scoped or unscoped), e.g. @slidev/theme-seriph or slidev-theme-foo.","For a local theme on disk, use a path form: /abs/path, @/alias, ./relative, or foo/bar relative.","Check for stray whitespace, uppercase, or punctuation and correct them."],"exampleFix":"// before: invalid name in headmatter\n---\ntheme: My Cool Theme\n---\n\n// after: valid npm package name\n---\ntheme: seriph\n---\n// or scoped:\n---\ntheme: @slidev/theme-seriph\n---","handlingStrategy":"validation","validationCode":"const RE_SAFE_PKG_NAME = /^(?:@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/\n\nfunction isValidPkgName(name: string): boolean {\n  return RE_SAFE_PKG_NAME.test(name)\n}\n\n// before configuring a theme/addon name:\nif (!isValidPkgName(name) && !name.startsWith('/') && !name.startsWith('@/') && name[0] !== '.') {\n  throw new Error(`Invalid theme/addon name: ${name}`)\n}","typeGuard":"function isSafePkgName(name: string): boolean {\n  // local-path forms bypass the npm-name check\n  if (name.startsWith('/') || name.startsWith('@/') || name[0] === '.') return true\n  return RE_SAFE_PKG_NAME.test(name)\n}","tryCatchPattern":"try {\n  return await resolveTheme(name, importer)\n} catch (e) {\n  if (e instanceof Error && /Invalid (theme|addon) name/.test(e.message)) {\n    return { error: 'Use a lowercase npm package name or a local path for the theme.' }\n  }\n  throw e\n}","preventionTips":["Use lowercase npm package names for themes/addons (scoped or unscoped).","For local themes, use a path form: /abs, @/alias, ./relative.","Trim whitespace and avoid uppercase/punctuation in headmatter theme: values.","Validate the name against RE_SAFE_PKG_NAME before booting Slidev in CI."],"tags":["resolver","theme","addon","validation","naming"],"backgroundTag":null,"analyzedSha":"0d798ace5828966d9f77f62094d5f7a971ad98f7","analyzedAt":"2026-08-12T17:10:56.221Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}