SP-2668: Allow profile recovery when the default profile cannot refresh - #426
Merged
Merged
Conversation
Zgjim Haziri (ZgjimHaziri)
force-pushed
the
SP-2668-profile-recovery
branch
2 times, most recently
from
September 15, 2026 15:24
ece82ee to
96c6aee
Compare
A failed token refresh reported the failure with logger.error(new FatalError), and the logger's custom transport calls process.exit(1) on any record carrying an error. Because the execution context loads the default profile before Commander dispatches the subcommand, the process died before any command ran -- including profile create and profile list, which the error message told the user to run. The only way out was pointing --profile at a name that does not exist. refreshProfile now warns and throws instead. Context.loadProfile already tolerates a rejected profile load, so startup finishes with no profile and profile management works; commands that need a connection still fail on first use of the http client. The guard now wraps issuer discovery too, so an unreachable team gets the same guidance as a rejected refresh token. The underlying cause is logged as text rather than as the error object, because a raw network error carries errno and the custom transport exits on that. Includes-AI-Code: true Co-authored-by: Cursor <cursoragent@cursor.com>
Zgjim Haziri (ZgjimHaziri)
force-pushed
the
SP-2668-profile-recovery
branch
from
September 15, 2026 15:28
96c6aee to
77fcca5
Compare
Zgjim Haziri (ZgjimHaziri)
marked this pull request as ready for review
September 15, 2026 16:06
Meris Nici (promeris)
previously approved these changes
Sep 17, 2026
The execution context loaded the default profile before Commander dispatched the subcommand, so every invocation refreshed the stored token -- including profile list and profile create, which never talk to the platform. A profile that could not refresh therefore warned on commands that had no use for it. Profile loading now runs in a preAction hook, and commands opt out with skipProfileLoading(). Subcommands inherit the opt-out by walking up the parent chain, so the profile and git profile families are marked once each and run without touching the stored profile. Commands that need a connection load it as before. The hook is wired in run() rather than createProgram() because tests build programs through createProgram with a hand-assembled context; registering it there would make every command test load the developer's real default profile and try to refresh it over the network. The recovery warning no longer names a command to run. Includes-AI-Code: true Co-authored-by: Cursor <cursoragent@cursor.com>
Sonar flags the fluent builder on new code; the sibling methods predate the quality gate and keep their concrete return type. Includes-AI-Code: true Co-authored-by: Cursor <cursoragent@cursor.com>
|
Meris Nici (promeris)
approved these changes
Sep 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Description
An expired default OAuth profile whose refresh failed made every
content-clisubcommand unusable — includingprofile createandprofile list, the commands the error message told users to run.A failed refresh reported itself with
logger.error(new FatalError(...)), and the logger's custom transport exits the process on any record carrying an error. Because the execution context loads the default profile before Commander dispatches the subcommand, the process died before any command ran.refreshProfilenow warns and throws instead. Startup finishes with no profile, so profile management works; commands that need a connection still fail on first use of the HTTP client.Relevant links
Checklist