{"record":{"id":"c19871fcf5fdf8dd","repo":"ruvnet/ruflo","slug":"token-stdin-no-input-received-on-stdin","errorCode":null,"errorMessage":"--token-stdin: no input received on stdin","messagePattern":"--token-stdin: no input received on stdin","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/auth/client.ts","lineNumber":181,"sourceCode":"    rl.close();\n  }\n  if (!code) throw new LoginCancelledError();\n\n  const tokens = await sec.exchangeManualCode(code, pkce.codeVerifier);\n  return { tokens, method: 'device' };\n}\n\n/**\n * `--token-stdin`: reads one JSON object from stdin,\n * `{access_token, refresh_token?, expires_in, scope}`. Wire format is not\n * specified by ADR-306 — defined here as typed JSON rather than a bare\n * token string, so scope/expiry are explicit rather than inferred.\n */\nexport async function tokenStdinLogin(input: NodeJS.ReadableStream = process.stdin): Promise<LoginResult> {\n  const chunks: Buffer[] = [];\n  for await (const chunk of input) chunks.push(chunk as Buffer);\n  const raw = Buffer.concat(chunks).toString('utf-8').trim();\n  if (!raw) throw new Error('--token-stdin: no input received on stdin');\n\n  let parsed: { access_token?: string; refresh_token?: string; expires_in?: number; scope?: string };\n  try {\n    parsed = JSON.parse(raw);\n  } catch {\n    throw new Error(\n      '--token-stdin expects a single JSON object: {\"access_token\",\"refresh_token\"?,\"expires_in\",\"scope\"}',\n    );\n  }\n  if (!parsed.access_token) throw new Error('--token-stdin: JSON is missing required field \"access_token\"');\n\n  const tokens: OAuthTokenResponse = {\n    access_token: parsed.access_token,\n    token_type: 'Bearer',\n    refresh_token: parsed.refresh_token,\n    expires_in: parsed.expires_in,\n  };\n  return { tokens, method: 'token-stdin' };","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/auth/client.ts#L163-L199","documentation":"tokenStdinLogin read stdin to EOF and got nothing but whitespace. The --token-stdin path expects exactly one JSON object ({access_token, refresh_token?, expires_in, scope}) on stdin; an empty stream means the caller invoked the flag without piping anything — typically a human running the command interactively, or a pipeline whose upstream produced no output.","triggerScenarios":"Running `ruflo auth login --token-stdin` in an interactive shell (no pipe attached — stdin is the TTY and may be closed/Ctrl-D'd), or `some-cmd | ruflo auth login --token-stdin` where some-cmd printed nothing (failed silently, empty secret).","commonSituations":"Scripts assuming a credential helper emits JSON when it actually failed quietly; interactive users exploring flags; CI steps where the secret-injection step was skipped or referenced an empty variable; Windows shells dropping pipe content.","solutions":["Verify the upstream producer: run `cat | whatever-emits-token` in isolation and confirm it prints the JSON object","Pipe explicitly, e.g. `cat token.json | ruflo auth login --token-stdin` or `ruflo auth login --token-stdin < token.json`","If the token comes from a secret store, fail that fetch loudly before invoking the CLI so empty output can't reach stdin","If you meant an interactive login, drop --token-stdin and use the default browser or manual flow"],"exampleFix":"# before — flag with nothing piped\nruflo auth login --token-stdin\n\n# after — explicit, fail-fast token source\ntoken=$(get_token) || exit 1\n[ -n \"$token\" ] || { echo 'token source empty'; exit 1; }\nprintf '%s' \"$token\" | ruflo auth login --token-stdin","handlingStrategy":"validation","validationCode":"// shell: refuse to invoke on empty input\n[ -s token.json ] || { echo 'token file empty'; exit 1; }\nruflo auth login --token-stdin < token.json\n\n// node: check the stream yields bytes before calling tokenStdinLogin\nconst chunks = [];\nfor await (const c of input) chunks.push(c);\nif (chunks.length === 0) throw new Error('no token on stdin — aborting before tokenStdinLogin');","typeGuard":null,"tryCatchPattern":"try { await tokenStdinLogin(process.stdin); }\ncatch (e) {\n  if (e instanceof Error && e.message.includes('no input received on stdin')) {\n    // fix the producer: nothing was piped; don't retry unchanged\n  }\n  throw e;\n}","preventionTips":["Always redirect from a file or pipe: --token-stdin is never interactive","Fail loudly in the secret-fetch step so empty tokens can't reach the CLI","Size-check the token file with [ -s ] before invoking"],"tags":["oauth","auth","stdin","cli","token"],"backgroundTag":"empty-stdin-input","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}