refactor: introduce TaskError typed error envelope (#660)#665
Conversation
Replace `TaskResult::Error(String)` with `TaskResult::Error(TaskError)`. TaskError provides typed error propagation with Display for user-facing messages and Debug for technical details, while From<String> ensures zero-breakage backwards compatibility with all existing code. - Create TaskError enum with Generic(String) + #[from] variants for SpvError, DashPayError, ConfigError, GroveSTARKError, WalletError - Wire TaskResult::Error(TaskError) through app.rs, connection_status.rs, and query_dpns_contested_resources.rs - Change run_backend_task to return Result<_, TaskError> - app.rs handler now shows Display text in banner + Debug in details - Document TaskError pattern in CLAUDE.md - Add manual test scenarios Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…arent errors - Add Other(Box<dyn Error + Send + Sync>) catch-all variant to TaskError - Show Debug details in error banner only in developer mode - Use #[error(transparent)] for proper error chain propagation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
MessageBanner on v1.0-dev takes &str, not impl Display. Convert TaskError to string before passing to set_global and with_details. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR migrates the backend task error system from Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/backend_task/mod.rs (1)
284-318:⚠️ Potential issue | 🟠 MajorBackend task signatures now diverge from the current repository error contract.
These signatures switch to
TaskError, but the active backend-task guideline still mandatesResult<T, String>. Please align the authoritative policy/tooling with this migration in the same change set, or keep this layer onStringuntil that policy update is in place.As per coding guidelines
src/backend_task/**/*.rs: Backend task errors should useResult<T, String>type where string errors display directly to users.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend_task/mod.rs` around lines 284 - 318, The new signatures use TaskError but repository policy requires Result<T, String>; change run_backend_tasks_concurrent and run_backend_task (and the synchronous run_backend_tasks) to return Vec<Result<BackendTaskSuccessResult, String>> and Result<BackendTaskSuccessResult, String> respectively, update the async closure in run_backend_tasks_concurrent to return Result<BackendTaskSuccessResult, String>, and convert any TaskError values inside these functions to String (e.g., map_err(|e| e.to_string()) or .to_string()) so the layer consistently uses Result<..., String> (references: run_backend_tasks_concurrent, run_backend_task, and the earlier run_backend_tasks loop).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/ai-design/2026-02-26-typed-errors/manual-tests.md`:
- Around line 146-151: Add a language identifier to the fenced code block
starting at the shown error example so markdownlint MD040 is satisfied: change
the opening fence from ``` to ```text (or another appropriate language like
```console), keeping the block contents and closing fence unchanged; this
targets the fenced block that begins with "[Error Banner - Red]" in
manual-tests.md.
---
Outside diff comments:
In `@src/backend_task/mod.rs`:
- Around line 284-318: The new signatures use TaskError but repository policy
requires Result<T, String>; change run_backend_tasks_concurrent and
run_backend_task (and the synchronous run_backend_tasks) to return
Vec<Result<BackendTaskSuccessResult, String>> and
Result<BackendTaskSuccessResult, String> respectively, update the async closure
in run_backend_tasks_concurrent to return Result<BackendTaskSuccessResult,
String>, and convert any TaskError values inside these functions to String
(e.g., map_err(|e| e.to_string()) or .to_string()) so the layer consistently
uses Result<..., String> (references: run_backend_tasks_concurrent,
run_backend_task, and the earlier run_backend_tasks loop).
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
CLAUDE.mddocs/ai-design/2026-02-26-typed-errors/manual-tests.mdsrc/app.rssrc/backend_task/contested_names/query_dpns_contested_resources.rssrc/backend_task/error.rssrc/backend_task/mod.rssrc/context/connection_status.rssrc/database/mod.rs
| ``` | ||
| [Error Banner - Red] | ||
| Message: "Failed to connect to RPC: connection timeout" | ||
| [▼ Details] | ||
| Details: RpcError { reason: "connection timeout", code: -1, ... } | ||
| ``` |
There was a problem hiding this comment.
Add a language identifier to the fenced block at Line 146.
This currently trips markdownlint MD040 (fenced-code-language).
📝 Proposed fix
-```
+```text
[Error Banner - Red]
Message: "Failed to connect to RPC: connection timeout"
[▼ Details]
Details: RpcError { reason: "connection timeout", code: -1, ... }</details>
<details>
<summary>🧰 Tools</summary>
<details>
<summary>🪛 markdownlint-cli2 (0.21.0)</summary>
[warning] 146-146: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
</details>
</details>
<details>
<summary>🤖 Prompt for AI Agents</summary>
Verify each finding against the current code and only fix it if needed.
In @docs/ai-design/2026-02-26-typed-errors/manual-tests.md around lines 146 -
151, Add a language identifier to the fenced code block starting at the shown
error example so markdownlint MD040 is satisfied: change the opening fence from
totext (or another appropriate language like ```console), keeping the
block contents and closing fence unchanged; this targets the fenced block that
begins with "[Error Banner - Red]" in manual-tests.md.
</details>
<!-- fingerprinting:phantom:medusa:hawk -->
<!-- This is an auto-generated comment by CodeRabbit -->
PastaPastaPasta
left a comment
There was a problem hiding this comment.
looks fine; I generally don't think we should be committing files like docs/ai-design/2026-02-26-typed-errors/manual-tests.md
Resolve merge conflicts from upstream v1.0-dev commits including: - TaskError typed error envelope refactor (dashpay#660/dashpay#665) - SPV client interface API changes (run() now takes command channel) - SyncState::Initializing new variant - FeeRate -> FeeLevel API change - NetworkExt trait import for known_genesis_block_hash - Various UI component updates (hint_text removal, ComponentStyles) Update e2e test code and kittest module list to work with current API. Keep both e2e feature flag additions and v1.0-dev improvements. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Issue being fixed or feature implemented
Refs #660 (Steps 1–4 of the migration strategy)
User Story
Imagine you are a developer working on Dash Evo Tool. When a backend task fails, the error is currently a plain
String— you can't distinguish a network timeout from a corrupted database from a bad user input. Now, errors are typed viaTaskError: the UI shows a clean user-facing message (Display), while developer mode reveals the full typed diagnostic (Debug). Adding a new error domain is just one#[from]variant away.Details
Replace
TaskResult::Error(String)withTaskResult::Error(TaskError)— a typed error envelope that preserves error origin while maintaining full backwards compatibility viaFrom<String>.What was done?
TaskErrorenum (src/backend_task/error.rs) with three tiers:Generic(String)+From<String>— zero-breakage backwards compat for all existing codeOther(Box<dyn Error + Send + Sync>)— catch-all for typed errors without a dedicated variant#[from]+#[error(transparent)]variants forSpvError,DashPayError,ConfigError,GroveSTARKError,WalletErrorrun_backend_taskreturnsResult<_, TaskError>— all domain runners still returnResult<_, String>, converted automatically viaFrom<String>app.rshandler usesDisplayfor banner text,Debugfor collapsible details (developer mode only)connection_status.rsadapted to use.to_string().contains(...)for RPC failure detectionTaskErrorpatterndocs/ai-design/2026-02-26-typed-errors/manual-tests.mdHow has this been tested?
cargo clippy --all-features --all-targets -- -D warnings— cleancargo +nightly fmt --all— cleandocs/ai-design/2026-02-26-typed-errors/manual-tests.mdBreaking Changes
None —
From<String>ensures all existingResult<T, String>code compiles unchanged.Checklist
🤖 Co-authored by Claudius the Magnificent AI Agent
Summary by CodeRabbit
Release Notes
Bug Fixes
Documentation