Skip to content

Env Var Placeholder Prevents Fallback to Stored Credentials #11614

@minijus

Description

@minijus

Verify latest release

  • I verified that the issue exists in the latest pnpm release

pnpm version

v11.1.1

Which area(s) of pnpm are affected? (leave empty if unsure)

CLI

Link to the code that reproduces this issue or a replay of the bug

No response

Reproduction steps

  1. Create .npmrc with an unresolved env var placeholder:

    registry=https://npm.example.com/artifactory/api/npm/my-npm-repo/
    //npm.example.com/artifactory/api/npm/my-npm-repo/:_authToken=${NPM_TOKEN}
    
  2. Ensure the env var is not set:

    unset NPM_TOKEN
  3. Log in to the registry (stores credentials locally):

    pnpm login --registry https://npm.example.com/artifactory/api/npm/my-npm-repo/

    (Enter valid credentials when prompted)

  4. Run:

    pnpm whoami

Describe the Bug

When .npmrc contains an unresolved environment variable placeholder (e.g., ${NPM_TOKEN}) and the environment variable is not set, pnpm whoami fails with a 401 error instead of falling back to credentials stored via pnpm login.

The error output is:

[WARN] Failed to replace env in config: ${NPM_TOKEN}
[ERR_PNPM_WHOAMI_FAILED] Failed to find the current user: 401

pnpm treats the unresolved placeholder as an authentication failure and does not attempt to use stored login credentials as a fallback.

Expected Behavior

pnpm should implement a fallback chain:

  1. If ${NPM_TOKEN} env var is set, use it for authentication
  2. If the env var is unset or unresolved, fall back to stored credentials from pnpm login
  3. pnpm whoami should succeed and display the logged-in username

This allows .npmrc to be safely committed to repos for CI use while local developers rely on their stored credentials when the env var is absent.


Use Case

Monorepos often share .npmrc across dev and CI environments:

  • CI: Sets NPM_TOKEN env var for automated authentication
  • Local dev: Should use credentials from pnpm login when env var is unset

Currently, developers must maintain separate .npmrc.local files (git-ignored) to work around this limitation.


Documentation Reference

According to https://pnpm.io/npmrc:

What is documented:

  • pnpm supports environment variable substitution: //registry.example.com/:_authToken=${NPM_TOKEN}
  • pnpm reads auth from multiple sources in priority order:
    1. .npmrc (project-level)
    2. <pnpm config>/auth.ini (where pnpm login stores credentials)
    3. ~/.npmrc (fallback)

What is NOT documented:

  • The fallback behavior when an env var placeholder is unresolved (unset in environment)
  • Whether pnpm should:
    • Treat an unresolved placeholder as a hard auth failure (current behavior)
    • Fall back to checking the next auth source (auth.ini from pnpm login)
    • Skip the placeholder and continue to other sources

The gap:
The docs show that env var substitution is a supported feature, but do not specify what happens when the referenced env var does not exist. This creates ambiguity for scenarios where .npmrc is shared between CI (with env var) and local dev (without env var, relying on pnpm login credentials).

The current behavior (hard failure on unresolved env var) breaks the expected fallback chain and forces developers to use workarounds like .npmrc.local files.

Which Node.js version are you using?

24.15.0

Which operating systems have you used?

  • macOS
  • Windows
  • Linux

If your OS is a Linux based, which one it is? (Include the version if relevant)

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions