Skip to content

fix(tauri): pre-flight every xdg-utils binary before register_all (#5V)#2416

Merged
graycyrus merged 1 commit into
tinyhumansai:mainfrom
oxoxDev:fix/sentry-5v-xdg-utils-preflight
May 21, 2026
Merged

fix(tauri): pre-flight every xdg-utils binary before register_all (#5V)#2416
graycyrus merged 1 commit into
tinyhumansai:mainfrom
oxoxDev:fix/sentry-5v-xdg-utils-preflight

Conversation

@oxoxDev
Copy link
Copy Markdown
Contributor

@oxoxDev oxoxDev commented May 21, 2026

Summary

  • Extends the existing Linux deep-link pre-flight from just xdg-mime to all three binaries tauri-plugin-deep-link::register_all shells out to: xdg-mime, update-desktop-database, xdg-icon-resource.
  • Skips the plugin call when any of them is missing on PATH — partial registration can't succeed, and the plugin's internal log::error! on the first missing binary is what was leaking to Sentry.
  • Closes OPENHUMAN-TAURI-5V (18 events). Sister bug to OPENHUMAN-TAURI-AS — same wire shape, different missing binary.

Problem

The original Wave 1 fix for OPENHUMAN-TAURI-AS pre-flighted only xdg-mime before calling app.deep_link().register_all(). That covered the WSL2 / fully-minimal-container case where xdg-utils is wholly absent.

But the plugin internally invokes three xdg-utils commands in sequence inside register_all:

  1. xdg-mime
  2. update-desktop-database
  3. xdg-icon-resource

On Linux installs where xdg-mime exists but one of the other two is missing (some partial / size-trimmed container images, certain bespoke minimal distros), the pre-flight passes but the plugin still hits a Failed to run OS command on step 2 or 3 — which surfaces in Sentry as:

Failed to run OS command `update-desktop-database`: No such file or directory (os error 2)

That's OPENHUMAN-TAURI-5V (18 events). The plugin emits this via log::error! inside register_all before returning the Err, so the existing if let Err arm downstream only catches the demoted user-visible failure — the internal log already escaped to sentry-tracing and produced an event.

Solution

Replace the single-binary check with a slice of all three, compute the missing subset, and skip register_all if the subset is non-empty:

const XDG_BINARIES: &[&str] =
    &[\"xdg-mime\", \"update-desktop-database\", \"xdg-icon-resource\"];
let missing: Vec<&str> = XDG_BINARIES
    .iter()
    .copied()
    .filter(|name| !path_has_executable(name))
    .collect();
if missing.is_empty() {
    if let Err(err) = app.deep_link().register_all() {
        log::warn!(\"[deep-link] register_all failed (non-fatal): {err}\");
    }
} else {
    log::warn!(
        \"[deep-link] skipping register_all — xdg-utils binaries missing on PATH: {} \
         (xdg-utils not installed; deep-link MIME registration unavailable on this host)\",
        missing.join(\", \")
    );
}

The warn log now enumerates exactly which binaries are missing so any future variant of this bug (a different partial install) is diagnosable from the local logs without a fresh Sentry event.

New test

path_has_executable_returns_false_for_partial_xdg_utils_install pins the partial-install case directly:

  • Builds a $PATH containing only xdg-mime (no update-desktop-database, no xdg-icon-resource).
  • Asserts the lookup correctly classifies each binary independently — xdg-mime → true, the other two → false.
  • Mirrors the OPENHUMAN-TAURI-5V wire shape exactly: that's the exact host configuration the 18 affected boots had.

Test is #[cfg(target_os = \"linux\")] (matches the existing sibling tests for path_has_executable_* predicates). CI Linux runner exercises it; the macOS local runner skips.

Submission Checklist

If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — changed lines (Vitest + cargo-llvm-cov merged via diff-cover) meet the gate enforced by .github/workflows/coverage.yml. New test covers the load-bearing partial-install branch; the early-return on missing.is_empty() is exercised by the existing path_has_executable_finds_file_on_path test.
  • N/A: behaviour-only change, no feature row impact. Coverage matrix updated — added/removed/renamed feature rows in docs/TEST-COVERAGE-MATRIX.md reflect this change.
  • All affected feature IDs from the matrix are listed in the PR description under ## Related.
  • No new external network dependencies introduced (mock backend used per Testing Strategy).
  • N/A: pre-flight extension is invisible at the user level — boots that previously logged a noisy Sentry event now log a warn and skip a no-op plugin call. No release-cut surface change. Manual smoke checklist updated if this touches release-cut surfaces (docs/RELEASE-MANUAL-SMOKE.md).
  • Linked issue closed via Closes #NNN in the ## Related section.

Impact

  • Runtime: Linux only. Boot now runs three path_has_executable lookups instead of one before the deep-link plugin call. Each is a $PATH split + is_file stat — negligible. Other platforms unchanged.
  • Performance: O(PATH_entries × 3) stat calls at app startup. Same big-O class as before. Adds ~tens of µs on a typical Linux desktop.
  • Security: no new attack surface. Lookups are read-only checks against the user's $PATH. The log::warn! enumerates binary names only — no paths, no PII.
  • Migration: none.
  • Compatibility: forward-compatible. On hosts that have all three binaries (the desktop-environment-installed default), behavior is identical to the pre-#5V pre-flight. On hosts missing one or more, the boot now logs a single warn naming which binaries to install — actionable diagnosis the previous code couldn't give.

Related

  • Closes OPENHUMAN-TAURI-5V
  • Related context: OPENHUMAN-TAURI-AS (Wave 1, originally introduced the xdg-mime pre-flight); tauri-plugin-deep-link internal log::error! shape that escapes the if let Err arm in this hook.
  • Follow-up PR(s)/TODOs: if tauri-plugin-deep-link gains a try_register_all_or_skip API or per-binary feature gating, this pre-flight becomes vestigial and can be deleted.

AI Authored PR Metadata (required for Codex/Linear PRs)

Keep this section for AI-authored PRs. For human-only PRs, mark each field N/A.

Linear Issue

  • Key: N/A (Sentry-driven triage; no Linear ticket)
  • URL: N/A

Commit & Branch

  • Branch: fix/sentry-5v-xdg-utils-preflight
  • Commit SHA: f4e6a4f (tip)

Agent

  • Claude Code (Opus 4.7, 1M context) running locally

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced stability of protocol handler registration on Linux. The application now checks for required system dependencies before attempting registration and gracefully skips the process when tools are unavailable, preventing unnecessary error logging.
  • Tests

    • Added regression test for systems with incomplete dependencies on Linux.

Review Change Stack

…er_all (OPENHUMAN-TAURI-5V)

Extend the existing Linux pre-flight in the Tauri setup hook from just
`xdg-mime` to all three binaries that `tauri-plugin-deep-link::register_all`
shells out to in sequence: `xdg-mime`, `update-desktop-database`, and
`xdg-icon-resource`. Skip the plugin call when *any* of them is missing.

The original OPENHUMAN-TAURI-AS pre-flight only checked `xdg-mime`, so a
host with `xdg-mime` installed but `update-desktop-database` missing
(small / minimal Linux installs, certain container images) still entered
`register_all`, which then fires
`log::error!("Failed to run OS command \`update-desktop-database\`…")`
internally before returning Err. That internal error log is scooped up
by `sentry-tracing` even though the user-visible failure was already
demoted to a warn by our `if let Err` arm — net effect is one Sentry
event per affected boot with no remediation path (the binary doesn't
exist on the host).

Partial registration can't succeed because the plugin runs all three
xdg-utils commands in sequence inside `register_all`; the first miss
kills the whole flow. Pre-flighting every binary preserves the existing
contract (no plugin call → no internal log → no Sentry event) while
extending coverage to the partial-install case the Wave-4 triage
surfaced.

Test: `path_has_executable_returns_false_for_partial_xdg_utils_install`
pins the contract by checking each binary independently with a $PATH
that contains only `xdg-mime` — mirrors the OPENHUMAN-TAURI-5V wire
shape exactly.

Closes OPENHUMAN-TAURI-5V
@oxoxDev oxoxDev requested a review from a team May 21, 2026 06:13
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2dce2afa-9570-44e0-a556-d20090561320

📥 Commits

Reviewing files that changed from the base of the PR and between c204a53 and f4e6a4f.

📒 Files selected for processing (1)
  • app/src-tauri/src/lib.rs

📝 Walkthrough

Walkthrough

Linux deep-link registration now preflights all three xdg-utils binaries (xdg-mime, update-desktop-database, xdg-icon-resource) before attempting registration, skipping the operation and logging the missing tools when any are absent, with a regression test validating correct detection of partial installations.

Changes

xdg-utils Binary Preflight for Deep-Link Setup

Layer / File(s) Summary
Deep-link binary preflight and conditional registration
app/src-tauri/src/lib.rs
Linux deep-link initialization now checks all three xdg-utils binaries required by register_all using path_has_executable, builds a list of missing binaries, skips registration when any are absent, and logs a warning naming the missing tools.
Partial xdg-utils installation regression test
app/src-tauri/src/lib.rs
Linux-only unit test ensures path_has_executable correctly reports xdg-mime as present and update-desktop-database and xdg-icon-resource as absent when only xdg-mime exists in a controlled $PATH.

Possibly related PRs

  • tinyhumansai/openhuman#1766: Both PRs modify app/src-tauri/src/lib.rs to gate tauri-plugin-deep-link::register_all using Linux path_has_executable preflight (this PR extends it to check multiple xdg-utils binaries beyond just xdg-mime).

Poem

🐰 A trio of tools now checked with care,
Before deep-linking dares to declare,
If xdg-mime or friends aren't there,
We log and skip with rabbit flair,
No crashes on systems halfway unprepared!

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: pre-flighting all xdg-utils binaries before calling register_all on Linux, which is the core objective of this PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@graycyrus graycyrus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, nice work!

@graycyrus graycyrus merged commit dcec585 into tinyhumansai:main May 21, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants