{"record":{"id":"57d336f2bd15a05c","repo":"jlcodes99/cockpit-tools","slug":"externalimport-app","errorCode":null,"errorMessage":"[ExternalImport][App] 读取当前应用版本失败，已终止外部导入","messagePattern":"\\[ExternalImport\\]\\[App\\] 读取当前应用版本失败，已终止外部导入","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/App.tsx","lineNumber":925,"sourceCode":"  const trayRefreshInFlightRef = useRef(false);\n  const openPlatformLayoutModal = useCallback(() => {\n    setPlatformLayoutRequestedGroupId(null);\n    setShowPlatformLayoutModal(true);\n  }, []);\n  const openBreakout = useCallback(() => {\n    setHasBreakoutSession(true);\n    setShowBreakout(true);\n  }, []);\n  const ensureExternalImportVersionCompatible = useCallback(\n    async (payload: ExternalProviderImportPayload): Promise<boolean> => {\n      const requiredVersion = payload.minAppVersion?.trim().replace(/^v/i, '');\n      if (!requiredVersion) return true;\n\n      let currentVersion = '';\n      try {\n        currentVersion = await getVersion();\n      } catch (error) {\n        console.warn('[ExternalImport][App] 读取当前应用版本失败，已终止外部导入', error);\n      }\n\n      if (currentVersion && !isVersionLowerThan(currentVersion, requiredVersion)) {\n        return true;\n      }\n\n      showModal({\n        title: t('common.shared.externalImport.versionUnsupportedTitle', '应用版本过低'),\n        description: t(\n          'common.shared.externalImport.versionUnsupportedDesc',\n          '暂不支持此方式，请下载最新版。',\n        ),\n        width: 'sm',\n        actions: [\n          {\n            id: 'check-update',\n            label: t('common.shared.externalImport.checkUpdate', '检查更新'),\n            variant: 'primary',","sourceCodeStart":907,"sourceCodeEnd":943,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/App.tsx#L907-L943","documentation":"Before accepting an external provider import, MainApp reads the current app version via Tauri's getVersion() to run a minimum-version check. If getVersion() rejects, currentVersion stays empty, the check is treated as failed, and the external import is deliberately terminated with this warning. This is a fail-closed safety gate against importing into an incompatible app version.","triggerScenarios":"await getVersion() rejects: the Tauri app API plugin (app metadata) is unavailable, running in a context where the tauri API isn't injected (plain browser/dev mismatch), or an IPC failure at startup.","commonSituations":"Dev server opened outside the Tauri WebView where getVersion doesn't exist; plugin version mismatch after upgrading Tauri; IPC not yet ready when the import payload arrives very early.","solutions":["Check the logged error — if getVersion is undefined, confirm the code runs inside the Tauri WebView and the app plugin is registered","Feature-detect: if typeof getVersion !== 'function', decide explicitly whether to skip the version gate in dev instead of silently terminating the import","Retry getVersion once with a small delay if the import arrives during startup races","Ensure tauri-plugin-app / withGlobalTauri configuration matches the version used by the frontend API package"],"exampleFix":"// before\ncurrentVersion = await getVersion();\n// after\ntry {\n  currentVersion = await getVersion();\n} catch (error) {\n  console.warn('[ExternalImport][App] 读取当前应用版本失败，已终止外部导入', error);\n  return false; // explicit fail-closed instead of empty-string fallthrough\n}","handlingStrategy":"fallback","validationCode":"async function readAppVersion(): Promise<string | null> {\n  try {\n    return await getVersion();\n  } catch {\n    return null;\n  }\n}","typeGuard":"function isSemver(v: string): boolean {\n  return /^\\d+\\.\\d+\\.\\d+/.test(v);\n}","tryCatchPattern":"let currentVersion = '';\ntry {\n  currentVersion = await getVersion();\n} catch (error) {\n  console.warn('[ExternalImport][App] 读取当前应用版本失败，已终止外部导入', error);\n  return false; // fail closed, don't import without a version gate\n}","preventionTips":["Feature-detect getVersion and decide explicitly how to behave outside the Tauri WebView (e.g. allow in dev)","Keep the Tauri app plugin version aligned with the frontend @tauri-apps/api package","Retry version reads once if the import arrives during startup","Log the underlying error, not just the warning message"],"tags":["tauri","version-check","external-import"],"backgroundTag":"tauri-api-unavailable","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}