{"record":{"id":"833abddbad01133e","repo":"ruvnet/ruflo","slug":"token-stdin-json-is-missing-required-field-acc","errorCode":null,"errorMessage":"--token-stdin: JSON is missing required field \"access_token\"","messagePattern":"--token-stdin: JSON is missing required field \"access_token\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/auth/client.ts","lineNumber":191,"sourceCode":" * `{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' };\n}\n\n/**\n * Refreshes an access token. Classifies failure into network-unreachable\n * vs. a reachable-but-erroring server so callers can print an honest\n * message instead of collapsing both into \"offline\" (ADR-308 failure\n * policy: local ruflo functionality is never affected by auth being\n * unavailable, but the diagnostic should say WHY it's unavailable).\n */\nexport async function refreshAccessToken(refreshTokenValue: string): Promise<OAuthTokenResponse> {","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/auth/client.ts#L173-L209","documentation":"Thrown by ruflo's token-stdin login path after stdin was successfully read and JSON.parse succeeded, but the resulting object has no truthy top-level `access_token` string. The CLI expects exactly one JSON object of the shape {\"access_token\", \"refresh_token\"?, \"expires_in\", \"scope\"}. It is a shape check on externally supplied credentials, not a network or auth-server failure.","triggerScenarios":"Running `ruflo auth login --token-stdin` and piping a JSON object that lacks `access_token`: e.g. {\"refresh_token\":\"...\"} only, a wrapper like {\"data\":{\"access_token\":...}}, {\"token\":\"...\"} with the wrong key name, or access_token:\"\" (empty string is falsy and rejected). Any valid JSON without a non-empty top-level access_token triggers it.","commonSituations":"CI pipelines piping tokens from a vault/IdP whose JSON envelope nests the token one level deep; scripts written against a different CLI's token format; copy-pasting an ID-token payload with a different field name; generating the payload with jq using the wrong key.","solutions":["Pipe a single flat JSON object with a non-empty top-level access_token: echo '{\"access_token\":\"eyJ...\",\"expires_in\":3600}' | ruflo auth login --token-stdin","If your source nests the token, unwrap it first: jq '{access_token: .data.access_token, expires_in: .expires_in}' | ruflo auth login --token-stdin","Verify the payload before sending: cat token.json | jq -e '.access_token | type == \"string\" and length > 0'","If you only hold a refresh token (no access token), use the interactive `ruflo auth login` flow instead of --token-stdin"],"exampleFix":"// before\necho '{\"refresh_token\":\"rt_123\"}' | ruflo auth login --token-stdin\n// after\necho '{\"access_token\":\"eyJhbGci...\",\"refresh_token\":\"rt_123\",\"expires_in\":3600,\"scope\":\"openid\"}' | ruflo auth login --token-stdin","handlingStrategy":"validation","validationCode":"const raw = await readStdin();\nlet parsed: unknown;\ntry { parsed = JSON.parse(raw); } catch { fail('stdin is not valid JSON'); }\nif (typeof (parsed as any)?.access_token !== 'string' || (parsed as any).access_token.length === 0) {\n  fail('payload needs a non-empty top-level \"access_token\" string');\n}\nawait login({ tokens: parsed as OAuthTokenResponse, method: 'token-stdin' });","typeGuard":"function isTokenStdinPayload(v: unknown): v is { access_token: string; refresh_token?: string; expires_in?: number; scope?: string } {\n  return typeof v === 'object' && v !== null &&\n    typeof (v as Record<string, unknown>).access_token === 'string' &&\n    (v as Record<string, unknown>).access_token!.length > 0;\n}","tryCatchPattern":"try {\n  await rufloLoginFromStdin();\n} catch (e) {\n  if (e instanceof Error && e.message.includes('missing required field \"access_token\"')) {\n    console.error('Expected: {\"access_token\":\"...\",\"refresh_token\"?,\"expires_in\",\"scope\"}');\n    process.exit(2);\n  }\n  throw e;\n}","preventionTips":["Validate the token JSON shape at the source (vault/CI secret) before piping it","Use jq -e '.access_token' as a pre-flight check in pipelines","Keep a canonical example payload in your runbook so operators copy the right shape"],"tags":["auth","oauth","cli","stdin","json","input-validation"],"backgroundTag":"oauth-token-missing-field","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"}