jlcodes99/cockpit-tools · error

未找到有效 Token {:?}

Error message

未找到有效 Token {:?}

What it means

During import_from_files, a JSON file parsed as a top-level object was inspected by extract_codex_tokens_from_value, which looks for known Codex token fields (accessToken/access_token, id_token + access_token, or refresh_token). When none of these token keys are found in the object, this error is logged and the file falls back to the Token/JSON import logic. It means the file is valid JSON but lacks the credential fields the importer recognizes.

Source

Thrown at crates/cockpit-core/src/modules/codex_account_core_mutations_quota.rs:57

        let parsed: serde_json::Value = match serde_json::from_str(&content) {
            Ok(v) => v,
            Err(e) => {
                logger::log_warn(&format!(
                    "Codex 文件旧规则 JSON 解析失败,将尝试 Token/JSON 导入逻辑 {:?}: {}",
                    file_path, e
                ));
                fallback_files.push((content, filename_label));
                continue;
            }
        };

        let before_count = candidates.len();
        match &parsed {
            serde_json::Value::Object(_) => {
                if let Some((tokens, hint)) = extract_codex_tokens_from_value(&parsed) {
                    candidates.push((tokens, hint, filename_label.clone()));
                } else {
                    logger::log_error(&format!("未找到有效 Token {:?}", file_path));
                }
            }
            serde_json::Value::Array(arr) => {
                for item in arr {
                    if let Some((tokens, hint)) = extract_codex_tokens_from_value(item) {
                        let label = item
                            .get("email")
                            .and_then(|v| v.as_str())
                            .unwrap_or(&filename_label)
                            .to_string();
                        candidates.push((tokens, hint, label));
                    }
                }
            }
            _ => {
                logger::log_error(&format!("不支持的 JSON 格式 {:?}", file_path));
            }
        }

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Open the file and confirm it contains at least one of accessToken/access_token, id_token+access_token, or refresh_token
  2. Re-authenticate with the Codex CLI so auth.json is regenerated with valid tokens
  3. Verify you are importing the auth file, not a config or settings file
  4. Check for renamed key casing (accessToken vs access_token) depending on CLI version

Example fix

// before (auth.json)
{ "OPENAI_API_KEY": "sk-..." }
// after
{ "tokens": { "id_token": "...", "access_token": "...", "refresh_token": "..." } }
Defensive patterns

Strategy: validation

Validate before calling

fn has_codex_tokens(v: &serde_json::Value) -> bool {
    let obj = match v { serde_json::Value::Object(o) => o, _ => return false };
    obj.contains_key("accessToken") || obj.contains_key("access_token")
        || obj.contains_key("refresh_token")
        || (obj.contains_key("id_token") && obj.contains_key("access_token"))
}
// call before import: if !has_codex_tokens(&parsed) { fix file first }

Type guard

fn is_json_object(v: &serde_json::Value) -> bool {
    matches!(v, serde_json::Value::Object(_))
}

Prevention

When it happens

Trigger: Calling import_from_files with a JSON file whose top-level is an object but which contains none of accessToken, access_token, id_token+access_token, or refresh_token — e.g. an auth.json that only has OPENAI_API_KEY, or a config/settings JSON dropped in by mistake.

Common situations: Users hand-edit auth.json and delete the tokens; importing a Codex config.json or settings file instead of auth.json; provider version changes renamed token fields; copying an empty or partially-written auth file.

Related errors


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