{"record":{"id":"edc9f9b7d0d68158","repo":"lbjlaq/Antigravity-Manager","slug":"common-tauri-api-not-loaded","errorCode":null,"errorMessage":"common.tauri_api_not_loaded","messagePattern":"common\\.tauri_api_not_loaded","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/services/accountService.ts","lineNumber":9,"sourceCode":"import i18n from '../i18n';\nimport { Account, DeviceProfile, DeviceProfileVersion, QuotaData } from '../types/account';\nimport { request as invoke } from '../utils/request';\n\n// 检查环境 (可选)\nfunction ensureTauriEnvironment() {\n    // Web 模式下 request 也是一个 function，所以这里不应抛错\n    if (typeof invoke !== 'function') {\n        throw new Error(i18n.t('common.tauri_api_not_loaded'));\n    }\n}\n\nexport async function listAccounts(): Promise<Account[]> {\n    const response = await invoke<any>('list_accounts');\n    // 如果返回的是对象格式 { accounts: [...] }, 则取其 accounts 属性\n    if (response && typeof response === 'object' && Array.isArray(response.accounts)) {\n        return response.accounts;\n    }\n    // 否则直接返回响应内容（假设为数组）\n    return response || [];\n}\n\nexport async function getCurrentAccount(): Promise<Account | null> {\n    return await invoke('get_current_account');\n}\n\nexport async function addAccount(email: string, refreshToken: string): Promise<Account> {","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/lbjlaq/Antigravity-Manager/blob/90a2b6b20797e2e593a83d0c54ab86037863fe70/src/services/accountService.ts#L1-L27","documentation":"ensureTauriEnvironment throws this when the injected Tauri invoke API is not available as a function. It guards calls to Tauri commands so the UI fails fast with an i18n message instead of crashing with 'invoke is not a function'. Note the source comments that in Web mode request is also a function, so this throw only fires when the module's import failed entirely.","triggerScenarios":"Calling startOAuthLogin, completeOAuthLogin or cancelOAuthLogin in a context where ../utils/request did not resolve to a callable (broken import, bundling issue, or running outside both Tauri and the Web request shim).","commonSituations":"Opening the bundle in a plain browser without the request shim wired up; a refactor renamed/removed the request export; a build misconfiguration tree-shook the invoke bridge.","solutions":["Verify src/utils/request.ts exports a callable `request` and that the import path in accountService.ts is correct","Rebuild the app so the Tauri/web invoke shim is bundled (check bundler aliases and tree-shaking config)","Confirm which mode the app runs in (Tauri vs web) and ensure web mode routes through the HTTP mapping in request.ts","Replace the throw with a clearer error naming the missing module for easier diagnosis"],"exampleFix":"// before\nif (typeof invoke !== 'function') {\n    throw new Error(i18n.t('common.tauri_api_not_loaded'));\n}\n// after\nif (typeof invoke !== 'function') {\n    throw new Error(`Tauri invoke bridge missing: got ${typeof invoke}. Check import of ../utils/request`);\n}","handlingStrategy":"try-catch","validationCode":"if (typeof invoke !== 'function') { console.warn('Tauri bridge unavailable; skipping native call'); }","typeGuard":"const isInvokable = (f: unknown): f is (...a: unknown[]) => Promise<unknown> => typeof f === 'function';","tryCatchPattern":"try { await startOAuthLogin(); } catch (e) { if (e?.message === i18n.t('common.tauri_api_not_loaded')) { showWebFallback(); } else throw e; }","preventionTips":["Always import the invoke bridge via the same wrapper module","Add a startup smoke test asserting the bridge is callable in both Tauri and web builds","Gate Tauri-only features behind a runtime capability check"],"tags":["tauri","environment","initialization"],"backgroundTag":"missing-dependency","analyzedSha":"90a2b6b20797e2e593a83d0c54ab86037863fe70","analyzedAt":"2026-09-19T08:34:01.322Z","contentChangedAt":"2026-09-19T08:34:01.322Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}