mastra-ai/mastra · error

Kimi For Coding token ${operation} response missing fields

Error message

Kimi For Coding token ${operation} response missing fields

What it means

credentialsFromTokenResponse validates the fields of a Kimi For Coding token endpoint response (access token, refresh token, finite positive expiresIn). If any required field is missing, empty, wrong type, or the expiry is non-positive, it throws with the operation name (e.g. 'poll' or 'refresh') embedded, indicating the server response did not match the expected token contract.

Source

Thrown at mastracode/sdk/src/auth/providers/kimi-coding.ts:87

    return null;
  }
}

function credentialsFromTokenResponse(value: unknown, operation: string, deviceId: string): OAuthCredentials {
  const data = (value ?? {}) as Record<string, unknown>;
  const access = data.access_token;
  const refresh = data.refresh_token;
  const expiresIn = data.expires_in;
  if (
    typeof access !== 'string' ||
    !access ||
    typeof refresh !== 'string' ||
    !refresh ||
    typeof expiresIn !== 'number' ||
    !Number.isFinite(expiresIn) ||
    expiresIn <= 0
  ) {
    throw new Error(`Kimi For Coding token ${operation} response missing fields`);
  }
  return { access, refresh, expires: Date.now() + expiresIn * 1000, deviceId };
}

export interface KimiCodingDeviceLoginPending {
  clientId: string;
  deviceId: string;
  deviceCode: string;
  userCode: string;
  url: string;
  instructions: string;
  state: DeviceCodePollState;
}

export type KimiCodingDevicePollResult =
  | { status: 'complete'; credentials: OAuthCredentials }
  | { status: 'pending'; nextPollMs: number; pending: KimiCodingDeviceLoginPending }
  | { status: 'failed'; error: string };

View on GitHub (pinned to 75dd419e61)

Solutions

  1. If this happened during polling, ensure the user completed device authorization before the token request succeeds
  2. Re-run the device login flow to obtain fresh tokens if refresh is failing
  3. Log the raw token-endpoint response body to identify which field is missing/wrong
  4. Check for a Kimi API change and update the SDK

Example fix

// before
const creds = await refreshKimiCodingToken(staleCreds); // throws
// after
try {
  creds = await refreshKimiCodingToken(staleCreds);
} catch (err) {
  if (String(err.message).includes('missing fields')) await login('kimi-coding');
  else throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the raw token payload yourself before passing it on
function looksLikeTokenPayload(d) {
  return !!d && typeof d === 'object' &&
    typeof d.access_token === 'string' && d.access_token &&
    typeof d.refresh_token === 'string' && d.refresh_token &&
    typeof d.expires_in === 'number' && Number.isFinite(d.expires_in) && d.expires_in > 0;
}

Type guard

function hasTokenFields(d: unknown): d is { access: string; refresh: string; expiresIn: number } {
  const o = d as Record<string, unknown>;
  return typeof o.access === 'string' && !!o.access &&
    typeof o.refresh === 'string' && !!o.refresh &&
    typeof o.expiresIn === 'number' && Number.isFinite(o.expiresIn) && o.expiresIn > 0;
}

Try / catch

try {
  creds = await refreshKimiCodingToken(creds);
} catch (err) {
  if (err instanceof Error && err.message.includes('missing fields')) {
    await login('kimi-coding'); // fall back to a full device login
  } else throw err;
}

Prevention

When it happens

Trigger: During device-login polling (pollKimiCodingTokenOnce) or token refresh (refreshKimiCodingToken), the token endpoint returns JSON lacking access/refresh/expires_in, or with expiresIn <= 0 / non-numeric — e.g. an error envelope, rate-limit body, or API change.

Common situations: Polling before authorization completed and receiving a non-token payload; expired refresh token returning an error object with 200; Kimi API outage or version drift altering field names; proxy injecting error pages with 2xx.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/0605702e93b2c9f1. Report an issue: GitHub.