Skip to content

[triage:ui-05-app-deeplink-fixed-sleep-race] Cold-start deep-link dispatch relies on a fixed 1500ms sleep (race) #155

Description

@ebursztein

Imported from Capsem triage report ui-05-app-deeplink-fixed-sleep-race.md.

  • Severity: low
  • Category: bug
  • Area: capsem-app
  • Location: crates/capsem-app/src/main.rs:278-289
  • Confidence: verified

Summary

On cold start with --connect <id>, the app waits a hard-coded 1500ms, then
evals if (window.__capsemDeepLink) { window.__capsemDeepLink({...}) }. If the
frontend has not yet mounted __capsemDeepLink after 1500ms (slow machine,
heavy first paint, debug build), the guard is false and the deep link is
silently dropped with no retry. There is no readiness handshake — the timeout is
a guess.

Evidence

// crates/capsem-app/src/main.rs:284
tauri::async_runtime::spawn(async move {
    tokio::time::sleep(std::time::Duration::from_millis(1500)).await;
    dispatch_deep_link(&window, &id, action.as_deref());   // fire once
});

dispatch_deep_link -> window.eval(build_deep_link_script(...)), and the
script is if (window.__capsemDeepLink) { ... } (main.rs:104-111) — a missing
hook is a no-op, not a retry.

Mitigation that exists: for the cold-start case the frontend also reads
connect/action from the URL query string in onMount
(frontend/src/lib/components/shell/App.svelte:53-69), so the initial launch
usually still opens the VM tab even if the eval fires too early. The eval path
is the only mechanism for the already-running (single-instance) case
(main.rs:266-277), but there the window is already mounted and dispatch is
immediate, so the 1500ms sleep does not apply.

Impact

Low: the cold-start eval can lose the deep link, but the URL-param path normally
covers that exact case, so user-visible breakage is unlikely. The fixed timeout
is nonetheless fragile and the eval path has no retry/handshake.

Suggested fix

Replace the fixed sleep with a readiness signal: have the frontend invoke a
deep_link_ready IPC command (or emit an event) once __capsemDeepLink is
installed, and dispatch from the Rust side on that signal. Failing that, retry
the eval a few times with backoff and stop once the hook responds.

Triage

Confirmed from the local reviewed report in /Users/elie/git/capsem/tmp/bugs/ui-05-app-deeplink-fixed-sleep-race.md. Track implementation in the triage sprint; add regression coverage before fixing.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions