pnpm/pnpm · error · PnpmError

PACKAGE_NAME_NOT_FOUND

PACKAGE_NAME_NOT_FOUND

Error message

Package name is not defined in the ${manifestFileName}.

What it means

pack.ts re-reads the manifest right before packing (because prepack/prepare scripts may rewrite it, and publishConfig.directory may point at a different directory) and requires a package name — without one there is no tarball filename and no registry document. The manifest file name in the message tells you which file (package.json normally) is missing the field.

Source

Thrown at pnpm11/releasing/commands/src/publish/pack.ts:255

    rootModulesDir: await realpathMissing(path.join(opts.dir, 'node_modules')),
    stdio: 'inherit',
    unsafePerm: true, // when running scripts explicitly, assume that they're trusted.
    userAgent: opts.userAgent,
  })
  if (!opts.ignoreScripts) {
    await _runScriptsIfPresent([
      'prepack',
      'prepare',
    ], entryManifest)
  }
  const dir = entryManifest.publishConfig?.directory
    ? path.join(opts.dir, entryManifest.publishConfig.directory)
    : opts.dir
  // always read the latest manifest, as "prepack" or "prepare" script may modify package manifest.
  const { manifest } = await readProjectManifest(dir, opts)
  preventBundledDependenciesWithoutHoistedNodeLinker(opts.nodeLinker, manifest)
  if (!manifest.name) {
    throw new PnpmError('PACKAGE_NAME_NOT_FOUND', `Package name is not defined in the ${manifestFileName}.`)
  }
  if (!validateNpmPackageName(manifest.name).validForOldPackages) {
    throw new PnpmError('INVALID_PACKAGE_NAME', `Invalid package name "${manifest.name}".`)
  }
  if (!manifest.version) {
    throw new PnpmError('PACKAGE_VERSION_NOT_FOUND', `Package version is not defined in the ${manifestFileName}.`)
  }
  const publishManifest = await createPublishManifest({
    projectDir: dir,
    modulesDir: path.join(opts.dir, 'node_modules'),
    manifest,
    embedReadme: opts.embedReadme,
    catalogs: opts.catalogs ?? {},
    hooks: opts.hooks,
    skipManifestObfuscation: opts.skipManifestObfuscation,
  })
  // Strip semver build metadata (the `+<build>` segment) from the published version so that
  // the tarball, the manifest packed inside it, and the metadata sent to the registry all agree.

View on GitHub (pinned to 6261b7f388)

Solutions

  1. Add a "name" field to the package.json in the directory being packed
  2. If publishConfig.directory is set, check the package.json inside that subdirectory too
  3. If a prepack/prepare script rewrites the manifest, make sure it preserves (or sets) the name

Example fix

// before
{
  "version": "1.0.0",
  "private": true
}

// after
{
  "name": "@my-org/artifact",
  "version": "1.0.0"
}
Defensive patterns

Strategy: validation

Validate before calling

const { manifest } = await readProjectManifest(dir)
if (!manifest.name) {
  throw new Error(`${dir}: package.json has no "name" — cannot pack`)
}

Type guard

interface NamedManifest extends ProjectManifest { name: string }

function hasName (manifest: ProjectManifest): manifest is NamedManifest {
  return typeof manifest.name === 'string' && manifest.name.length > 0
}

Prevention

When it happens

Trigger: pnpm pack or pnpm publish in a directory whose package.json has no "name"; a prepack/prepare script that regenerates package.json without the name; publishConfig.directory pointing at a subdir whose package.json lacks a name.

Common situations: Packing a generated artifact directory; attempting to publish a manifest stub created for tooling; scripts that strip fields from package.json during prepack.

Related errors


AI-assisted analysis of pnpm/pnpm@6261b7f388 (2026-08-17). Data as JSON: /api/errors/8e84ec6290b9a4d4. Report an issue: GitHub.