jlcodes99/cockpit-tools · warning

[ExternalImport][App] 读取当前应用版本失败,已终止外部导入

Error message

[ExternalImport][App] 读取当前应用版本失败,已终止外部导入

What it means

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.

Source

Thrown at src/App.tsx:925

  const trayRefreshInFlightRef = useRef(false);
  const openPlatformLayoutModal = useCallback(() => {
    setPlatformLayoutRequestedGroupId(null);
    setShowPlatformLayoutModal(true);
  }, []);
  const openBreakout = useCallback(() => {
    setHasBreakoutSession(true);
    setShowBreakout(true);
  }, []);
  const ensureExternalImportVersionCompatible = useCallback(
    async (payload: ExternalProviderImportPayload): Promise<boolean> => {
      const requiredVersion = payload.minAppVersion?.trim().replace(/^v/i, '');
      if (!requiredVersion) return true;

      let currentVersion = '';
      try {
        currentVersion = await getVersion();
      } catch (error) {
        console.warn('[ExternalImport][App] 读取当前应用版本失败,已终止外部导入', error);
      }

      if (currentVersion && !isVersionLowerThan(currentVersion, requiredVersion)) {
        return true;
      }

      showModal({
        title: t('common.shared.externalImport.versionUnsupportedTitle', '应用版本过低'),
        description: t(
          'common.shared.externalImport.versionUnsupportedDesc',
          '暂不支持此方式,请下载最新版。',
        ),
        width: 'sm',
        actions: [
          {
            id: 'check-update',
            label: t('common.shared.externalImport.checkUpdate', '检查更新'),
            variant: 'primary',

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Check the logged error — if getVersion is undefined, confirm the code runs inside the Tauri WebView and the app plugin is registered
  2. Feature-detect: if typeof getVersion !== 'function', decide explicitly whether to skip the version gate in dev instead of silently terminating the import
  3. Retry getVersion once with a small delay if the import arrives during startup races
  4. Ensure tauri-plugin-app / withGlobalTauri configuration matches the version used by the frontend API package

Example fix

// before
currentVersion = await getVersion();
// after
try {
  currentVersion = await getVersion();
} catch (error) {
  console.warn('[ExternalImport][App] 读取当前应用版本失败,已终止外部导入', error);
  return false; // explicit fail-closed instead of empty-string fallthrough
}
Defensive patterns

Strategy: fallback

Validate before calling

async function readAppVersion(): Promise<string | null> {
  try {
    return await getVersion();
  } catch {
    return null;
  }
}

Type guard

function isSemver(v: string): boolean {
  return /^\d+\.\d+\.\d+/.test(v);
}

Try / catch

let currentVersion = '';
try {
  currentVersion = await getVersion();
} catch (error) {
  console.warn('[ExternalImport][App] 读取当前应用版本失败,已终止外部导入', error);
  return false; // fail closed, don't import without a version gate
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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