Skip to content

fix: read piped access token from stdin instead of prompting @W-22954140@#1526

Merged
soridalac merged 1 commit into
mainfrom
wr/fixAccessTokenStdinPrompt
Jul 20, 2026
Merged

fix: read piped access token from stdin instead of prompting @W-22954140@#1526
soridalac merged 1 commit into
mainfrom
wr/fixAccessTokenStdinPrompt

Conversation

@WillieRuemmele

Copy link
Copy Markdown
Contributor

Summary

  • sf org login access-token crashed with Error (13): User force closed the prompt with 13 null when an access token was piped via stdin and an auth file already existed for that user. The command consumed stdin for the token prompt, then fired a second interactive "overwrite existing file?" confirm prompt against an already-exhausted stdin, which inquirer rejects → unresolved top-level await → Node exit 13. Empty/EOF stdin hit the same crash.
  • Fix: when stdin is not a TTY (the piped / CI case), read the token directly from the stream instead of using the interactive secret prompt, and skip the overwrite confirm (treat it like --no-prompt, since there's no way to answer it).
  • A 60s timeout guards against a stdin stream that is opened but never sends data or EOF, so the command fails with a clear message instead of hanging. Interactive-TTY, --no-prompt, and SF_ACCESS_TOKEN/SFDX_ACCESS_TOKEN env-var paths are unchanged.

Fixes forcedotcom/cli#3573

Work Item

@W-22954140@: sf auth accesstoken store failing with "User force closed the prompt with 13 null"

Regression window

The stdin token reader was rewritten in #902 ("feat: use new inquirer") to use an interactive @inquirer/password prompt. Piping a token then hitting a second @inquirer/confirm prompt against a non-TTY/exhausted stdin is what produces the exit-13 crash. Reported as working in 2.136.8, broken from the next release.

Proof of Work

Verified against a local build (bin/run.js):

Scenario Before After
Pipe token + existing auth file Error (13) Successfully authorized (exit 0)
Empty stdin (true | sf ...) Error (13) clean "access token isn't in the correct format" (exit 1)
SF_ACCESS_TOKEN + --no-prompt works works (unchanged)
  • Unit tests: 89 passing (12 in the access-token suite, including new cases: read piped token, trims whitespace, empty-stdin error, non-TTY skips overwrite prompt, timeout path, stdin-error cleanup)
  • Type check (tsc): clean
  • Lint (eslint src/...): clean

Validation

Two independent adversarial cold reviews (diff-only, no implementation context) were run. Findings addressed:

  • Added tests that drive the real readPipedStdin path (not just the env-var short-circuit)
  • Added a read timeout + explicit listener cleanup to avoid an indefinite hang / dangling read / unhandled rejection
  • Stubbed token env vars in stdin tests to remove environment-dependent flakiness
  • Documented the piped-stdin behavior in the command help

Test plan

  • echo "<orgId>!<token>" | sf org login access-token --instance-url <url> succeeds when an auth file already exists (no prompt, no exit 13)
  • Interactive sf org login access-token --instance-url <url> in a real terminal still prompts for the token and for overwrite
  • SF_ACCESS_TOKEN=<token> sf org login access-token --instance-url <url> --no-prompt still works

…140@

When an access token is piped to 'sf org login access-token' and an auth
file already exists for that user, the command triggered an interactive
overwrite confirm against an already-consumed stdin, crashing with
'User force closed the prompt with 13 null' (Node exit 13).

Read the token directly from stdin when it is not a TTY, and skip the
overwrite confirm in that non-interactive case. A timeout guards against
a stdin stream that never sends data or EOF.

Fixes #3573
@WillieRuemmele
WillieRuemmele requested a review from a team as a code owner July 15, 2026 20:02
@WillieRuemmele

Copy link
Copy Markdown
Contributor Author

verified as well:

➜  dreamhouse-lwc git:(main) ✗  hub:(DevHub) scratch:(ccresorts) ➜  echo $(pbpaste) | sf org login access-token --instance-url https://ccresortscom-f-dev-ed.develop.my.salesforce.com
✔ Access token of user to use for authentication
? A file already exists for user "willie@ccresorts.com", which is associated with the access token you provided.
Are you sure you want to overwrite the existing file? (y/N) 

Error (13): User force closed the prompt with 13 null


➜  dreamhouse-lwc git:(main) ✗  hub:(DevHub) scratch:(ccresorts) ➜  echo $(pbpaste) | ../../oss/plugin-auth/bin/run.js org login access-token --instance-url https://ccresortscom-f-dev-ed.develop.my.salesforce.com 
Successfully authorized willie@ccresorts.com with org ID 00Dg7000007C0t6EAC

@soridalac

Copy link
Copy Markdown
Contributor

QA notes:

✅: Pipe token + existing auth file: successfully authorized
✅: Empty stdin (true |): clean format error, no crash
✅: Interactive TTY (no pipe): prompts for token as expected
✅: SF_ACCESS_TOKEN + --no-prompt: successfully authorized

@soridalac
soridalac merged commit 8d67a5e into main Jul 20, 2026
14 checks passed
@soridalac
soridalac deleted the wr/fixAccessTokenStdinPrompt branch July 20, 2026 21:59
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.

sf auth accesstoken store failing with User force closed the prompt with 13 null

2 participants