jlcodes99/cockpit-tools · error

Claude login start 响应缺少关键字段

Error message

Claude login start 响应缺少关键字段

What it means

normalizeClaudeDesktopLoginStartResponse validates the backend response for starting a Claude Desktop login and throws when neither loginId nor userDataDir can be extracted. Those two fields are mandatory to track the pending login session; numeric fields get safe defaults instead.

Source

Thrown at src/services/claudeService.ts:41

};

export interface ClaudeCliLaunchInfo {
  accountId: string;
  accountEmail: string;
  workingDir: string;
  launchCommand: string;
}

function normalizeClaudeDesktopLoginStartResponse(
  raw: ClaudeDesktopLoginStartResponseRaw,
): ClaudeDesktopLoginStartResponse {
  const loginId = raw.loginId ?? raw.login_id ?? '';
  const userDataDir = raw.userDataDir ?? raw.user_data_dir ?? '';
  const expiresIn = Number(raw.expiresIn ?? raw.expires_in ?? 0);
  const intervalSeconds = Number(raw.intervalSeconds ?? raw.interval_seconds ?? 0);

  if (!loginId || !userDataDir) {
    throw new Error('Claude login start 响应缺少关键字段');
  }

  return {
    loginId,
    userDataDir,
    expiresIn: Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn : 1800,
    intervalSeconds: Number.isFinite(intervalSeconds) && intervalSeconds > 0 ? intervalSeconds : 2,
  };
}

function normalizeClaudeOAuthStartResponse(raw: ClaudeOAuthStartResponseRaw): ClaudeOAuthStartResponse {
  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);

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

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Log the raw response from the backend command to see which fields are actually returned
  2. Verify the Rust command returns loginId and userDataDir (or login_id/user_data_dir) and that the Tauri serde rename attributes match
  3. Update frontend normalization to match any recent backend field rename
  4. Retry the login after confirming the Claude Desktop binary/environment is available

Example fix

// before
const raw = await invoke('claude_desktop_login_start'); // returned {}
// after
// backend: return Ok(json!({ "loginId": id, "userDataDir": dir })) and assert fields in tests
Defensive patterns

Strategy: try-catch

Validate before calling

const raw = /* backend response */;
const loginId = raw?.loginId ?? raw?.login_id ?? '';
const userDataDir = raw?.userDataDir ?? raw?.user_data_dir ?? '';
if (!loginId || !userDataDir) throw new Error('Claude login start 响应缺少关键字段');

Type guard

function isValidLoginStart(r: unknown): r is { loginId: string; userDataDir: string } {
  const o = r as any;
  return !!(o && (o.loginId || o.login_id) && (o.userDataDir || o.user_data_dir));
}

Try / catch

try {
  const start = await claudeDesktopLoginStart();
} catch (e) {
  if (e instanceof Error && e.message.includes('缺少关键字段')) {
    showLoginError('Login start failed: incomplete response from backend.');
  } else throw e;
}

Prevention

When it happens

Trigger: The Tauri backend response for Claude Desktop login start omits or empties loginId/login_id and/or userDataDir/user_data_dir (both camelCase and snake_case are checked).

Common situations: Backend command updated or failing silently, returning an error object instead of the login payload, a mismatched contract between frontend types and the Rust command, or the browser session failing to spawn so no user data dir is produced.

Related errors


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