jlcodes99/cockpit-tools · info

Tauri save failed, falling back to web download

Error message

Tauri save failed, falling back to web download

What it means

In MfaVaultManager's handleExport, the export first tries the native path: Tauri's save dialog (dialog.save) plus writeTextFile to the chosen path. If any part throws (dialog unavailable, write permission denied, not running under Tauri), it logs this warning and falls back to a browser-style Blob + anchor download. The export still succeeds via the fallback in most cases.

Source

Thrown at src/components/MfaVaultManager.tsx:336

        secret: record.secret,
        time: record.time,
      }));

      const dataStr = JSON.stringify(exportList, null, 2);
      const defaultFilename = `twofa_saved_export_${new Date().toISOString().split('T')[0]}.json`;

      try {
        const filePath = await save({
          filters: [{ name: 'JSON', extensions: ['json'] }],
          defaultPath: defaultFilename,
        });

        if (filePath) {
          await writeTextFile(filePath, dataStr);
        }
        return;
      } catch (e) {
        console.warn('Tauri save failed, falling back to web download', e);
      }

      const blob = new Blob([dataStr], { type: 'application/json' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = defaultFilename;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    } catch {}
  };

  const handleImport = async () => {
    try {
      let dataStr = '';
      try {

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Check the logged `e` — if in a browser/dev server, the fallback download is expected behavior.
  2. Ensure tauri-plugin-dialog and tauri-plugin-fs are installed and allowlisted in the Tauri capabilities config.
  3. Verify the selected save directory is writable (permissions, cloud-sync placeholders, antivirus).
  4. Use the fallback download that already triggered and confirm the exported JSON file is intact.

Example fix

// tauri.conf.json capabilities
// before
"permissions": []
// after
"permissions": [
  "dialog:default",
  "fs:allow-write-text-file"
]
Defensive patterns

Strategy: fallback

Validate before calling

// detect Tauri runtime before attempting native save
const isTauri = '__TAURI_INTERNALS__' in window;
if (!isTauri) {
  triggerWebDownload(dataStr, fileName);
  return;
}

Type guard

function isTauriEnvironment(): boolean {
  return typeof window !== 'undefined' && '__TAURI_INTERNALS__' in window;
}

Try / catch

try {
  const filePath = await save({ defaultPath: fileName });
  if (filePath) await writeTextFile(filePath, dataStr);
  return;
} catch (e) {
  console.warn('Tauri save failed, falling back to web download', e);
}
triggerWebDownload(dataStr, fileName); // Blob + anchor fallback

Prevention

When it happens

Trigger: The Tauri API call fails during MFA vault export: dialog plugin not registered/permitted, chosen path unwritable, save cancelled resulting in null handled as error, or the code running in a plain web context where @tauri-apps/api is unavailable.

Common situations: Running the frontend in a browser during development (no Tauri runtime), missing tauri-plugin-dialog/fs in capabilities config, OS denying write to the selected directory, or CSP blocking the plugin invoke.

Related errors


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