Zackriya-Solutions/meetily · warning

Import already in progress

Error message

Import already in progress

What it means

start_import (import.rs:263) tries to acquire the ImportGuard via compare_exchange on the global IMPORT_IN_PROGRESS AtomicBool and loses the race - another import is currently running in this process. The guard is a deliberate single-flight mechanism (RAII Drop clears the flag, so even a panic cannot leave it stuck) preventing two imports from writing meetings/transcripts concurrently and contending for the whisper/parakeet engines.

Source

Thrown at frontend/src-tauri/src/audio/import.rs:263

    debug!(
        "Extracted metadata: {}Hz, {} frames, {:.2}s",
        sample_rate, n_frames, duration_seconds
    );

    Ok(duration_seconds)
}

/// Start import of an audio file
pub async fn start_import<R: Runtime>(
    app: AppHandle<R>,
    source_path: String,
    title: String,
    language: Option<String>,
    model: Option<String>,
    provider: Option<String>,
) -> Result<ImportResult> {
    // Acquire guard - ensures flag is cleared even on panic/early return
    let _guard = ImportGuard::acquire().map_err(|e| anyhow!(e))?;

    // Reset cancellation flag
    IMPORT_CANCELLED.store(false, Ordering::SeqCst);

    let use_parakeet = provider.as_deref() == Some("parakeet");
    let result = run_import(
        app.clone(),
        source_path,
        title,
        language,
        model,
        provider,
    )
    .await;

    // Unload the engine after the batch job (success, failure, or cancellation)
    super::common::unload_engine_after_batch(use_parakeet).await;

View on GitHub (pinned to 0281737d87)

Solutions

  1. Retry after the current import completes - the error is transient by design; subscribe to the import progress events to know when it is safe.
  2. Make the frontend idempotent: disable the Import button synchronously on click and re-enable only on the terminal import-completed/import-error event.
  3. If the UI believes nothing is running but the error persists, an import may still be finishing; wait for its event or restart the app (Drop guarantees the flag clears when the task ends).
  4. For programmatic callers: await the first invocation's future before starting a second; never fire-and-forget import invokes.
  5. Check app logs: 'Starting import for ...' lines show which import currently holds the guard.

Example fix

// frontend: before - button stays enabled, double-click double-invokes
const onImport = () => invoke('import_audio_file', payload);

// frontend: after - single-flight guard keyed to the running request
const importingRef = useRef(false);
const onImport = async () => {
  if (importingRef.current) return;
  importingRef.current = true;
  try { await invoke('import_audio_file', payload); }
  finally { importingRef.current = false; }
};
Defensive patterns

Strategy: validation

Validate before calling

// Frontend: single-flight guard so the second invoke never happens
const importingRef = useRef(false);
async function importFile(payload) {
  if (importingRef.current) { setStatus('busy'); return; }
  importingRef.current = true;
  try { return await invoke('import_audio_file', payload); }
  finally { importingRef.current = false; }
}

Try / catch

// Treat as transient: wait for the running import's terminal event, then retry once
try { await invoke('import_audio_file', payload); }
catch (e) {
  if (String(e).includes('Import already in progress')) {
    await waitForEvent('import-completed', 'import-error');
    return invoke('import_audio_file', payload); // single retry after drain
  }
  throw e;
}

Prevention

When it happens

Trigger: Double-clicking Import before the first click's async invoke disabled the button; frontend state desync - the button re-enabled after a transient render while the backend import still runs; invoking import_audio_file twice in quick succession (retry logic that does not await the first call); hot-reload re-mounting a component whose effect fires the import again.

Common situations: Janky UI where the disable-button effect lags the invoke; users spamming the button on slow disks; dev hot-reload double-firing effects; automated tests invoking import in parallel.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16). Data as JSON: /api/errors/9728a0009e3f1de7. Report an issue: GitHub.