jlcodes99/cockpit-tools · error

Trae OAuth start 响应缺少关键字段

Error message

Trae OAuth start 响应缺少关键字段

What it means

normalizeTraeOAuthStartResponse validates the Trae device-authorization start response. The device-link flow cannot proceed without loginId and verificationUri (camelCase or snake_case); if both lookups yield empty values the library throws this error ('Trae OAuth start response missing key fields') rather than returning a half-usable session.

Source

Thrown at src/services/traeService.ts:31

}

type TraeOAuthStartResponseRaw = Partial<TraeOAuthStartResponse> & {
  login_id?: string;
  verification_uri?: string;
  expires_in?: number;
  interval_seconds?: number;
  callback_url?: string | null;
};

function normalizeTraeOAuthStartResponse(raw: TraeOAuthStartResponseRaw): TraeOAuthStartResponse {
  const loginId = raw.loginId ?? raw.login_id ?? '';
  const verificationUri = raw.verificationUri ?? raw.verification_uri ?? '';
  const expiresIn = Number(raw.expiresIn ?? raw.expires_in ?? 0);
  const intervalSeconds = Number(raw.intervalSeconds ?? raw.interval_seconds ?? 0);
  const callbackUrl = raw.callbackUrl ?? raw.callback_url ?? null;

  if (!loginId || !verificationUri) {
    throw new Error('Trae OAuth start 响应缺少关键字段');
  }

  return {
    loginId,
    verificationUri,
    expiresIn: Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn : 600,
    intervalSeconds: Number.isFinite(intervalSeconds) && intervalSeconds > 0 ? intervalSeconds : 1,
    callbackUrl,
  };
}

export async function listTraeAccounts(): Promise<TraeAccount[]> {
  return await invoke('list_trae_accounts');
}

export async function deleteTraeAccount(accountId: string): Promise<void> {
  return await invoke('delete_trae_account', { accountId });
}

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Inspect the raw HTTP response body for loginId and verificationUri
  2. Confirm the request hits the correct Trae OAuth endpoint (check base URL/proxy config)
  3. Update the app so client and backend OAuth contracts match (both naming styles are handled)
  4. Retry the start call; if reproducible, capture the payload and report it

Example fix

// before
const session = await traeOauthLoginStart();
// after
try {
  const session = await traeOauthLoginStart();
} catch (e) {
  console.error('Trae OAuth start failed:', e.message, rawBody);
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const raw = await res.clone().json();
if (!(raw?.loginId ?? raw?.login_id) || !(raw?.verificationUri ?? raw?.verification_uri)) {
  console.error('Trae OAuth start body malformed:', raw);
}

Type guard

function hasOAuthStartFields(v: unknown): v is { loginId: string; verificationUri: string } {
  const r = v as any;
  return !!(r?.loginId ?? r?.login_id) && !!(r?.verificationUri ?? r?.verification_uri);
}

Try / catch

try {
  const session = await traeOauthLoginStart();
} catch (e) {
  if (String(e.message).includes('缺少关键字段')) {
    showRetryDialog('Trae login could not start — verify endpoint/proxy and retry');
  } else throw e;
}

Prevention

When it happens

Trigger: Calling traeOauthLoginStart when the backend response omits loginId or verificationUri/verification_uri — an error body returned with HTTP 200, a gateway/proxy altering the payload, or an API schema change between client and server versions.

Common situations: Trae service outage returning error JSON, misconfigured base URL pointing at a wrong endpoint, or stale app version after a backend field rename.

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/17b69fb400b53af3. Report an issue: GitHub.