ruvnet/ruflo · error · Error
--token-stdin: JSON is missing required field "access_token"
Error message
--token-stdin: JSON is missing required field "access_token"
What it means
Thrown by tokenStdinLogin when the parsed JSON object lacks the required access_token field. Other fields (refresh_token, expires_in, scope) are tolerated, but access_token is mandatory.
Source
Thrown at v3/@claude-flow/cli/src/auth/client.ts:191
* `{access_token, refresh_token?, expires_in, scope}`. Wire format is not
* specified by ADR-306 — defined here as typed JSON rather than a bare
* token string, so scope/expiry are explicit rather than inferred.
*/
export async function tokenStdinLogin(input: NodeJS.ReadableStream = process.stdin): Promise<LoginResult> {
const chunks: Buffer[] = [];
for await (const chunk of input) chunks.push(chunk as Buffer);
const raw = Buffer.concat(chunks).toString('utf-8').trim();
if (!raw) throw new Error('--token-stdin: no input received on stdin');
let parsed: { access_token?: string; refresh_token?: string; expires_in?: number; scope?: string };
try {
parsed = JSON.parse(raw);
} catch {
throw new Error(
'--token-stdin expects a single JSON object: {"access_token","refresh_token"?,"expires_in","scope"}',
);
}
if (!parsed.access_token) throw new Error('--token-stdin: JSON is missing required field "access_token"');
const tokens: OAuthTokenResponse = {
access_token: parsed.access_token,
token_type: 'Bearer',
refresh_token: parsed.refresh_token,
expires_in: parsed.expires_in,
};
return { tokens, method: 'token-stdin' };
}
/**
* Refreshes an access token. Classifies failure into network-unreachable
* vs. a reachable-but-erroring server so callers can print an honest
* message instead of collapsing both into "offline" (ADR-308 failure
* policy: local ruflo functionality is never affected by auth being
* unavailable, but the diagnostic should say WHY it's unavailable).
*/
export async function refreshAccessToken(refreshTokenValue: string): Promise<OAuthTokenResponse> {View on GitHub (pinned to 6b01dc5a68)
Solutions
- Ensure the JSON includes access_token as a non-empty string.
- If you only hold a refresh token, use the interactive/manual PKCE flow or keychain profile, not --token-stdin.
Example fix
// before
{ "refresh_token": "..." }
// after
{ "access_token": "...", "refresh_token": "...", "expires_in": 3600 } Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof parsed.access_token !== 'string' || parsed.access_token.length === 0) {
throw new Error('JSON is missing a non-empty string field "access_token"');
} Type guard
function hasAccessToken(v: unknown): v is { access_token: string } {
return !!v && typeof v === 'object' && typeof (v as { access_token?: unknown }).access_token === 'string' && (v as { access_token: string }).access_token.length > 0;
} Prevention
- Validate required keys immediately after parse, before constructing the token.
- Adopt a schema (e.g. zod) for the token wire format.
- Reject empty-string access tokens, not just missing ones.
When it happens
Trigger: Piping JSON like {"token":"..."} (wrong field name) or a refresh-only object that has no access_token key.
Common situations: Producer used a different field name; refresh-token object mistaken for an access-token object; partial copy-paste.
Related errors
- --token-stdin: no input received on stdin
- --token-stdin expects a single JSON object: {"access_token",
- state mismatch — the OAuth callback did not match the reques
- login cancelled: no code was entered
- Could not reach the Cognitum auth service. ruflo core functi
AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12).
Data as JSON: /api/errors/833abddbad01133e.
Report an issue: GitHub.