jlcodes99/cockpit-tools · error

Codex 导入失败 {}: {}

Error message

Codex 导入失败 {}: {}

What it means

Per-file Codex account import failure log emitted inside import_from_files (src-tauri/src/modules/codex_account_mutations_quota.rs:142). When upsert_account_with_hints fails for one credential file and the error is NOT a disk-full condition, the label (file name/email) and underlying error are logged and the file is appended to the `failed` list; the import of remaining files continues. It is a non-fatal, per-account failure, not an abort of the whole batch.

Source

Thrown at src-tauri/src/modules/codex_account_mutations_quota.rs:142

                }
                logger::log_info(&format!("Codex 导入成功: {}", account.email));
                imported.push(account);
            }
            Err(e) => {
                if is_disk_full_error_message(&e) {
                    logger::log_error(&format!(
                        "Codex 导入因磁盘空间不足终止: label={}, imported={}, error={}",
                        label,
                        imported.len(),
                        e
                    ));
                    return Err(format!(
                        "磁盘空间不足,已终止导入(已成功 {} 个)。{}",
                        imported.len(),
                        e
                    ));
                }
                logger::log_error(&format!("Codex 导入失败 {}: {}", label, e));
                failed.push(CodexFileImportFailure {
                    email: label,
                    error: e,
                });
            }
        }
    }

    for (content, label, auth_file_plan_type) in fallback_files {
        progress_index += 1;
        if let Some(app_handle) = crate::get_app_handle() {
            use tauri::Emitter;
            let _ = app_handle.emit(
                "codex:file-import-progress",
                serde_json::json!({
                    "current": progress_index,
                    "total": total,
                    "email": &label,

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Inspect the per-file error text logged next to the label to see why upsert_account_with_hints rejected the token file
  2. Re-export or re-login that account in Codex CLI to obtain a fresh valid auth file (containing access_token/id_token or refresh_token) and re-import
  3. Check that the file is valid JSON with the expected token keys before importing
  4. If storage is implicated but not detected as disk-full, verify free space and write permissions on the app data directory
  5. Collect results from the returned failed list (CodexFileImportFailure) instead of expecting the whole call to fail

Example fix

// before: blind bulk import of every file in a folder
import_from_files(paths).await?;
// after: pre-validate JSON token keys and skip invalid files
for p in paths {
    let content = fs::read_to_string(&p)?;
    let ok = serde_json::from_str::<serde_json::Value>(&content)
        .map(|v| v.get("access_token").is_some()
            || v.get("accessToken").is_some()
            || v.get("refresh_token").is_some())
        .unwrap_or(false);
    if !ok { log::warn!("skipping invalid token file: {}", p.display()); continue; }
}
Defensive patterns

Strategy: validation

Validate before calling

fn is_importable_codex_file(path: &Path) -> bool {
    std::fs::read_to_string(path).ok()
        .and_then(|c| serde_json::from_str::<serde_json::Value>(&c).ok())
        .map(|v| v.get("access_token").is_some()
            || v.get("accessToken").is_some()
            || v.get("refresh_token").is_some())
        .unwrap_or(false)
}

Type guard

fn has_valid_tokens(v: &serde_json::Value) -> bool {
    v.get("access_token").and_then(|t| t.as_str()).map(|s| !s.is_empty()).unwrap_or(false)
        || v.get("refresh_token").and_then(|t| t.as_str()).map(|s| !s.is_empty()).unwrap_or(false)
}

Try / catch

match import_from_files(paths).await {
    Ok(result) => {
        for f in &result.failed {  // Vec<CodexFileImportFailure>
            eprintln!("账号 {} 导入失败: {}", f.email, f.error);
        }
    }
    Err(e) => eprintln!("导入中止: {e}"),
}

Prevention

When it happens

Trigger: Calling import_from_files with old-format candidate files where upsert_account_with_hints(tokens, account_id_hint, None) returns Err — e.g. a token file missing accessToken/access_token/id_token/refresh_token fields, malformed JSON, an account_id_hint that conflicts with stored data, or a storage write error that is not disk-full.

Common situations: Bulk-importing a directory of auth JSON files where some are stale, hand-edited, truncated, or from an incompatible Codex CLI version; duplicate email labels colliding with existing accounts; corrupted files copied from another machine.

Related errors


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