Skip to content

fix(observability): skip Sentry for local-AI "<x> binary not found" errors (OPENHUMAN-TAURI-9N)#1669

Merged
senamakel merged 2 commits into
tinyhumansai:mainfrom
CodeGhost21:fix/observability-skip-local-ai-binary-missing-9n
May 13, 2026
Merged

fix(observability): skip Sentry for local-AI "<x> binary not found" errors (OPENHUMAN-TAURI-9N)#1669
senamakel merged 2 commits into
tinyhumansai:mainfrom
CodeGhost21:fix/observability-skip-local-ai-binary-missing-9n

Conversation

@CodeGhost21
Copy link
Copy Markdown
Contributor

@CodeGhost21 CodeGhost21 commented May 13, 2026

Summary

  • Adds ExpectedErrorKind::LocalAiBinaryMissing to the observability classifier so local-AI RPCs that fail because piper / whisper.cpp / Ollama isn't installed stop being captured as Sentry errors.
  • Anchors the substring match on \"binary not found\", the shared marker emitted from four call sites in local_ai/.
  • Logged at info! in report_expected_message, mirroring the existing LocalAiDisabled path — sentry-tracing records a breadcrumb, not an error.

Fixes OPENHUMAN-TAURI-9N (2 events on 0.53.22, Windows user in Saratov, RU, elapsed_ms=1 — synchronous binary-presence check).

Why this is noise, not signal

The local-AI service deliberately returns these errors so the UI can prompt the user to install/configure the binary. The error message itself is the user-facing remediation ("Set PIPER_BIN or install piper."). It's a pure user-environment condition — we can't install the binary for them, and Sentry has no remediable signal.

Same category as the existing local ai is disabled skip.

Wire shapes covered

All four contain \"binary not found\":

  • \"piper binary not found. Set PIPER_BIN or install piper.\"service/speech.rs:199, hit by local_ai_tts
  • \"whisper.cpp binary not found. Set WHISPER_BIN or install whisper-cli.\"service/speech.rs:164, hit by local_ai_stt
  • \"Ollama binary not found at '<path>'. Provide a valid path to the ollama executable.\"schemas.rs:828
  • \"Ollama installed but binary not found on system\"service/ollama_admin.rs:50

Test plan

  • cargo test --lib core::observability::tests — 13 tests pass, including the two new classifier tests.
  • classifies_local_ai_binary_missing_errors covers all four canonical wire shapes plus the wrapped rpc.invoke_method failed: … form that hits the classifier in production.
  • does_not_classify_unrelated_messages_as_binary_missing pins the anchor against false positives (spawn failures, empty transcripts) that mention binaries in unrelated contexts.
  • cargo check --lib — no new warnings.
  • cargo fmt.

Summary by CodeRabbit

  • Bug Fixes

    • Improved detection and reporting for missing local-AI binary errors, including clearer info-level logging for expected cases to aid troubleshooting.
  • Tests

    • Added comprehensive tests covering various "binary not found" message variants and negative cases to prevent misclassification.

Review Change Stack

…rrors (OPENHUMAN-TAURI-9N)

`local_ai_tts` / `local_ai_stt` / Ollama admin RPCs return deliberate
user-state errors when the required local binary isn't installed on the
host. The wire shapes today are:

  - "piper binary not found. Set PIPER_BIN or install piper."
    (service/speech.rs:199, hit by `local_ai_tts`)
  - "whisper.cpp binary not found. Set WHISPER_BIN or install whisper-cli."
    (service/speech.rs:164, hit by `local_ai_stt`)
  - "Ollama binary not found at '<path>'. Provide a valid path to the
    ollama executable."
    (schemas.rs:828)
  - "Ollama installed but binary not found on system"
    (service/ollama_admin.rs:50)

All four are user-environment conditions — the error message itself is
the user-facing remediation ("Set PIPER_BIN or install piper.") — and
carry no remediable signal for Sentry. Today they flow through
`rpc.invoke_method` → `report_error_or_expected` and get captured as
error events (OPENHUMAN-TAURI-9N: 2 events on `0.53.22`, Windows user
in Saratov, RU, elapsed_ms=1 — synchronous binary-presence check).

Extend `expected_error_kind` with a new `LocalAiBinaryMissing` variant,
anchored on the shared substring `"binary not found"`. Logged at
`info!` via `report_expected_message` so the sentry-tracing layer
records at most a breadcrumb — same pattern as `LocalAiDisabled`.

Tests:
- `classifies_local_ai_binary_missing_errors` exercises all four
  canonical wire shapes plus the wrapped `rpc.invoke_method failed: …`
  form that reaches the classifier in production.
- `does_not_classify_unrelated_messages_as_binary_missing` pins the
  anchor against false positives (spawn failures, empty transcripts,
  download failures) that mention binaries in unrelated contexts and
  should still surface as real Sentry events.
@CodeGhost21 CodeGhost21 requested a review from a team May 13, 2026 17:25
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 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: f4c7cad2-8f91-46a3-a2ac-d8fad9b64394

📥 Commits

Reviewing files that changed from the base of the PR and between d673a23 and 13100e2.

📒 Files selected for processing (1)
  • src/core/observability.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/core/observability.rs

📝 Walkthrough

Walkthrough

Adds an ExpectedErrorKind::LocalAiBinaryMissing variant, classifies "binary not found" messages as that kind, logs an info breadcrumb when encountered, and adds tests for positive and negative classification cases.

Changes

Local AI Binary Missing Error Handling

Layer / File(s) Summary
ExpectedErrorKind contract extension
src/core/observability.rs
ExpectedErrorKind enum gains the LocalAiBinaryMissing variant as a new classification target for missing AI service binaries.
Binary not found classification
src/core/observability.rs
expected_error_kind classifier is extended to recognize "binary not found" substrings (case-insensitive) in error messages and map them to the new LocalAiBinaryMissing variant.
Binary missing error logging
src/core/observability.rs
report_expected_message adds a match arm for LocalAiBinaryMissing that logs an info-level breadcrumb indicating the local AI binary-missing error is being skipped.
Classification and logging tests
src/core/observability.rs
Unit tests verify that expected_error_kind correctly classifies multiple "binary not found" message shapes (from Piper, Whisper.cpp, and Ollama, including RPC-wrapped variants) as LocalAiBinaryMissing, and that unrelated "binaries" messages (permission denied, spawn failure, empty transcript) are not misclassified.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • tinyhumansai/openhuman#1601: Both PRs modify src/core/observability.rs's ExpectedErrorKind plus the expected_error_kind/report_error_or_expected expected-message classification flow—this PR adds LocalAiBinaryMissing, while that PR adds transport/transient expected kinds and routes call sites through the same "expected" breadcrumb path.

Suggested reviewers

  • senamakel
  • graycyrus

Poem

🐰 A little binary lost its way,
I sniffed the error and knew what to say,
"binary not found" — now neatly tagged,
Logged with a breadcrumb, no panic ragged,
Hoppy fixes hop in to play. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding observability handling to skip Sentry for local-AI binary-not-found errors, matching the PR's core objective of reducing false-positive error reporting.
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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/observability.rs`:
- Around line 53-55: The current classifier treats any error containing "binary
not found" as ExpectedErrorKind::LocalAiBinaryMissing, which is too broad;
update the match in observability.rs so the branch that returns
ExpectedErrorKind::LocalAiBinaryMissing only triggers when the lowercased error
contains "binary not found" AND also includes a local-AI provider marker such as
"piper", "whisper.cpp", or "ollama" (check for these substrings alongside the
existing check), keeping the same return value and the function/match structure
that evaluates lower; this narrows the rule to local-AI flows and prevents
suppressing unrelated errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2018738f-3874-4a0f-9975-02507a513c1e

📥 Commits

Reviewing files that changed from the base of the PR and between c05de92 and d673a23.

📒 Files selected for processing (1)
  • src/core/observability.rs

Comment thread src/core/observability.rs
Comment on lines +53 to +55
if lower.contains("binary not found") {
return Some(ExpectedErrorKind::LocalAiBinaryMissing);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Narrow the binary-missing classifier to local-AI providers only.

Line 53 currently matches any error containing "binary not found", which can suppress Sentry for unrelated failures outside local-AI flows. Restrict this branch with local-AI markers (e.g., piper, whisper.cpp, ollama) to avoid observability blind spots.

Suggested fix
-    if lower.contains("binary not found") {
+    if lower.contains("binary not found")
+        && (lower.contains("piper")
+            || lower.contains("whisper.cpp")
+            || lower.contains("ollama"))
+    {
         return Some(ExpectedErrorKind::LocalAiBinaryMissing);
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if lower.contains("binary not found") {
return Some(ExpectedErrorKind::LocalAiBinaryMissing);
}
if lower.contains("binary not found")
&& (lower.contains("piper")
|| lower.contains("whisper.cpp")
|| lower.contains("ollama"))
{
return Some(ExpectedErrorKind::LocalAiBinaryMissing);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/observability.rs` around lines 53 - 55, The current classifier
treats any error containing "binary not found" as
ExpectedErrorKind::LocalAiBinaryMissing, which is too broad; update the match in
observability.rs so the branch that returns
ExpectedErrorKind::LocalAiBinaryMissing only triggers when the lowercased error
contains "binary not found" AND also includes a local-AI provider marker such as
"piper", "whisper.cpp", or "ollama" (check for these substrings alongside the
existing check), keeping the same return value and the function/match structure
that evaluates lower; this narrows the rule to local-AI flows and prevents
suppressing unrelated errors.

…ng-9n

# Conflicts:
#	src/core/observability.rs
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