Skip to content

fix(config): gracefully handle configDependencies errors during config commands#11362

Merged
zkochan merged 11 commits into
pnpm:mainfrom
fpapado:fix-config-deps-fetch
May 5, 2026
Merged

fix(config): gracefully handle configDependencies errors during config commands#11362
zkochan merged 11 commits into
pnpm:mainfrom
fpapado:fix-config-deps-fetch

Conversation

@fpapado

@fpapado fpapado commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Closes #10684. Running pnpm config set triggers resolveAndInstallConfigDeps before the new config (e.g. auth token) is saved to .npmrc, causing a 401 crash when the config dependency is hosted in a private registry.

This patch adds a tolerateConfigDependenciesErrors flag to installConfigDepsAndLoadHooks. For cmd === 'config', 'set' and 'get', installation failures are now caught and logged at debug level so the command can proceed and actually write / read the auth token.

pnpm set and pnpm get are separate top-level commands whose handlers delegate to the config command internally, so they are explicitly listed alongside 'config'; users can hit #10684 via any of the three entry points.

Plugin pnpmfile paths from configDependencies are resolved by checking each file's existence on disk, so previously-installed hooks survive a transient install failure and requireHooks won't throw PNPMFILE_NOT_FOUND when nothing has been installed yet.

Covers the fix with:

  • Unit tests in pnpm/test/getConfig.test.ts exercising the installConfigDepsAndLoadHooks contract (success, tolerated error, rethrown error, store creation/close errors propagating) and the on-disk pnpmfile resolution behavior.
  • Four e2e tests in pnpm/test/configurationalDependencies.test.ts that spawn the pnpm CLI against a bogus configDependency and assert each entrypoint (pnpm config set, pnpm config get, pnpm set, pnpm get) still works.

@fpapado fpapado force-pushed the fix-config-deps-fetch branch from 2f244f9 to ba3bcd7 Compare April 27, 2026 13:12
@fpapado fpapado marked this pull request as ready for review April 28, 2026 05:46
@fpapado fpapado requested a review from zkochan as a code owner April 28, 2026 05:46
Copilot AI review requested due to automatic review settings April 28, 2026 05:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes pnpm CLI config-related commands so they don’t crash when configDependencies installation fails (e.g. missing auth token), allowing pnpm config set/get (and the pnpm set/get entrypoints) to proceed and update/read .npmrc.

Changes:

  • Add an option to installConfigDepsAndLoadHooks to catch configDependencies install errors and log them at debug level.
  • Enable this error-tolerant mode for pnpm config, pnpm set, and pnpm get in the CLI entrypoint.
  • Add unit + e2e regression coverage and a changeset entry.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pnpm/src/getConfig.ts Adds catchConfigDependenciesErrors option, debug logging on failure, and guards pnpmfile path prepending.
pnpm/src/main.ts Enables catching configDependencies install errors for config/set/get command entrypoints.
pnpm/test/getConfig.test.ts Unit tests for installConfigDepsAndLoadHooks success vs. caught vs. thrown failure behavior.
pnpm/test/configurationalDependencies.test.ts E2E regression tests ensuring config writes/reads work even when configDependencies fails.
.changeset/major-hats-press.md Records the patch-level change for release notes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pnpm/src/getConfig.ts
Comment thread pnpm/src/main.ts
Running `pnpm config set` triggers `resolveAndInstallConfigDeps` before the
new config (e.g. auth token) is saved to `.npmrc`, causing a 401 crash when
the config dependency is hosted in a private registry.

This patch adds a `catchConfigDependenciesErrors` flag to
`installConfigDepsAndLoadHooks`. For `cmd === 'config'`, `'set'` and `'get'`,
installation failures are now caught and logged at debug level so the command
can proceed and actually write / read the auth token. When the install fails,
plugin pnpmfile paths are not prepended either (they don't exist on disk yet),
so `requireHooks` won't blow up with PNPMFILE_NOT_FOUND.

`pnpm set` and `pnpm get` are separate top-level commands whose handlers
delegate to the `config` command internally, so they are explicitly listed
alongside `'config'` — users can hit pnpm#10684 via any of the three entry points.

Covers the fix with:
- Unit tests in pnpm/test/getConfig.test.ts exercising the
  `installConfigDepsAndLoadHooks` contract (success, caught-error, default-throw).
- Three e2e tests in pnpm/test/configurationalDependencies.test.ts that spawn
  the real pnpm CLI against a bogus configDependency and assert each entry
  point (`pnpm config set`, `pnpm set`, `pnpm get`) still works.

Fixes pnpm#10684
@zkochan zkochan force-pushed the fix-config-deps-fetch branch from ba3bcd7 to 9ffa6f4 Compare May 5, 2026 10:28
@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

installConfigDepsAndLoadHooks gains an option to tolerate config-dependency install failures; when enabled for the CLI commands config, set, and get, install errors are logged at debug level and the command continues. Plugin pnpmfile resolution now yields .cjs only when that file exists.

Changes

Config Dependency Error Tolerance

Layer / File(s) Summary
API Signature
pnpm/src/getConfig.ts
installConfigDepsAndLoadHooks(config, context, opts?) gains opts?: { tolerateConfigDependenciesErrors?: boolean }.
Core Implementation
pnpm/src/getConfig.ts
resolveAndInstallConfigDeps(...) is wrapped in try/catch; by default errors are rethrown, but when opts.tolerateConfigDependenciesErrors is true the install error is logged via logger.debug (error message extracted using util.types.isNativeError) and swallowed. Store controller creation/close remains guarded by finally. calcPnpmfilePathsOfPluginDeps now yields pnpmfile.cjs only if that file exists on disk.
Command Wiring
pnpm/src/main.ts
main calls installConfigDepsAndLoadHooks(..., { tolerateConfigDependenciesErrors }) with the flag enabled when cmd is config, set, or get.
Unit Tests
pnpm/test/getConfig.test.ts
Adds jest.unstable_mockModule mocks and loggerMock/storeCloseMock; expands beforeEach; adds tests for skipping missing pnpmfiles; adds installConfigDepsAndLoadHooks suite covering success, tolerant failure (logs and does not throw), default failure (throws), and propagation of store creation/close errors even when tolerance is enabled.
Integration / Regression Tests
pnpm/test/configurationalDependencies.test.ts
Adds writeFailingConfigDep() helper and four regression tests asserting pnpm config set/get and pnpm set/get still perform expected .npmrc read/write behavior when a configDependencies install fails.
Changeset Metadata
.changeset/major-hats-press.md
New changeset documenting that pnpm config, pnpm set, and pnpm get tolerate configDependencies install failures by logging at debug level and continuing; other commands still report the error.

Sequence Diagram

sequenceDiagram
    autonumber
    participant Client
    participant CLI
    participant getConfig
    participant Installer
    participant Store
    participant Logger

    Client->>CLI: run command (config / set / get or other)
    CLI->>getConfig: installConfigDepsAndLoadHooks(opts.tolerateConfigDependenciesErrors = cmd in {config,set,get})
    getConfig->>Store: create store controller
    getConfig->>Installer: resolveAndInstallConfigDeps(...)
    alt install succeeds
        Installer-->>getConfig: success
        getConfig->>Store: ensure store closed
        getConfig-->>CLI: return hooks/config
    else install fails
        Installer-->>getConfig: throws error
        alt tolerateConfigDependenciesErrors = true
            getConfig->>Logger: logger.debug("Failed to install configDependencies", error)
            getConfig->>Store: ensure store closed
            getConfig-->>CLI: continue without installed config deps
        else
            getConfig-->>CLI: rethrow error (command fails)
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Suggested reviewers

  • zkochan

Poem

🐰
I hopped through configs, small and spry,
If deps fall down I only sigh—then try.
A debug whisper keeps the logs polite,
The store is closed and commands march on at night.
Carrots saved, the CLI stays bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR fully addresses issue #10684 by implementing tolerateConfigDependenciesErrors flag for config/set/get commands, preventing crashes when config dependencies fail to install during credential updates.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked objective: tolerating config dependency errors for config commands, improving pnpmfile path resolution, and adding comprehensive unit/e2e tests.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: adding graceful error handling for configDependencies failures during config commands, which is the primary objective of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Address review feedback on PR pnpm#11362:
- Replace the configDepsInstalled boolean with on-disk existence checks
  in calcPnpmfilePathsOfPluginDeps so already-installed config dep hooks
  from a previous run are still picked up when a subsequent install
  fails transiently.
- Add e2e coverage for `pnpm config get` to match the existing
  `pnpm config set`, `pnpm set`, and `pnpm get` cases.
Copilot AI review requested due to automatic review settings May 5, 2026 10:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pnpm/src/getConfig.ts
Per review feedback on PR pnpm#11362: the outer try/catch around
createStoreController + resolveAndInstallConfigDeps + the close in
finally was swallowing store creation and close errors when
catchConfigDependenciesErrors was enabled, mislabeling them as install
failures. Move createStoreController out of the catch and wrap only
resolveAndInstallConfigDeps, while keeping the close in finally.

Adds unit tests verifying store creation and close errors propagate
even when catchConfigDependenciesErrors is true.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pnpm/test/getConfig.test.ts`:
- Around line 123-135: Move the helper function buildBaseConfig so it is
declared after the tests that call it within the same describe block: locate all
usages of buildBaseConfig in the describe block and cut the current
buildBaseConfig declaration, then paste it below those call sites (after the
last test that uses it) so the file follows the hoisting-based ordering rule;
ensure the function name and signature (buildBaseConfig(): { config: Config,
context: ConfigContext }) remain unchanged and run tests to verify no
regressions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c7f378c7-e490-4205-8c00-217de5e73e84

📥 Commits

Reviewing files that changed from the base of the PR and between a0e480f and c804664.

📒 Files selected for processing (2)
  • pnpm/src/getConfig.ts
  • pnpm/test/getConfig.test.ts

Comment thread pnpm/test/getConfig.test.ts Outdated
Per repo style rule (functions are declared after they are used,
relying on hoisting). Addresses CodeRabbit review feedback on PR pnpm#11362.
Copilot AI review requested due to automatic review settings May 5, 2026 11:38
…figDependenciesErrors

`tolerate` describes the behavior intent (proceed despite the failure)
rather than the low-level mechanism (catch). No functional change.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .changeset/major-hats-press.md Outdated
zkochan added 2 commits May 5, 2026 13:42
…inally

The outer `try { inner-try-catch } finally { close }` and inner
`try { install } catch { log }` are equivalent to a flat
`try { install } catch { log } finally { close }`. createStoreController
stays outside the try so its errors still propagate; close stays in
finally so its errors aren't matched by catch.
Copilot AI review requested due to automatic review settings May 5, 2026 11:44
zkochan added 2 commits May 5, 2026 13:46
The guard in main.ts triggers for any `pnpm config` subcommand (not
just set/get), plus `pnpm set` and `pnpm get`. Update the changeset to
match.
@zkochan zkochan changed the title fix(config): gracefully handle configDependencies errors during config set/get commands fix(config): gracefully handle configDependencies errors during config commands May 5, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pnpm/src/getConfig.ts Outdated
zkochan added 2 commits May 5, 2026 13:51
…is missing

Address review feedback: previously calcPnpmfilePathsOfPluginDeps
silently skipped any plugin without an on-disk pnpmfile, which masked
misconfigured plugin packages (plugin dir present but no pnpmfile).

Now the function only skips when the plugin directory is missing
entirely (install didn't happen). When the directory exists but
neither pnpmfile.mjs nor pnpmfile.cjs is present, the .cjs path is
still yielded so requireHooks can surface PNPMFILE_NOT_FOUND for the
misconfigured plugin.
@zkochan zkochan enabled auto-merge (squash) May 5, 2026 11:57
@zkochan zkochan merged commit 0c137bb into pnpm:main May 5, 2026
9 checks passed
zkochan added a commit that referenced this pull request May 5, 2026
…g commands (#11362)

Closes #10684. Running `pnpm config set` triggers `resolveAndInstallConfigDeps` before the new config (e.g. auth token) is saved to `.npmrc`, causing a 401 crash when the config dependency is hosted in a private registry.

This patch adds a `tolerateConfigDependenciesErrors` flag to `installConfigDepsAndLoadHooks`. For `cmd === 'config'`, `'set'` and `'get'`, installation failures are now caught and logged at debug level so the command can proceed and actually write / read the auth token.

`pnpm set` and `pnpm get` are separate top-level commands whose handlers delegate to the `config` command internally, so they are explicitly listed alongside `'config'`; users can hit #10684 via any of the three entry points.

Plugin pnpmfile paths from `configDependencies` are resolved by checking each file's existence on disk, so previously-installed hooks survive a transient install failure and `requireHooks` won't throw `PNPMFILE_NOT_FOUND` when nothing has been installed yet.

Covers the fix with:
- Unit tests in `pnpm/test/getConfig.test.ts` exercising the `installConfigDepsAndLoadHooks` contract (success, tolerated error, rethrown error, store creation/close errors propagating) and the on-disk pnpmfile resolution behavior.
- Four e2e tests in `pnpm/test/configurationalDependencies.test.ts` that spawn the pnpm CLI against a bogus `configDependency` and assert each entrypoint (`pnpm config set`, `pnpm config get`, `pnpm set`, `pnpm get`) still works.

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pnpm config set inconsistently installs config dependencies

3 participants