Skip to content

refactor: remove TaskError::Generic and TaskError::Other, replace with specialized variants#744

Merged
lklimek merged 6 commits into
task/660-i18n-ready-strings-general-rulefrom
copilot/remove-generic-task-errors
Mar 13, 2026
Merged

refactor: remove TaskError::Generic and TaskError::Other, replace with specialized variants#744
lklimek merged 6 commits into
task/660-i18n-ready-strings-general-rulefrom
copilot/remove-generic-task-errors

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 12, 2026

Eliminates the Generic(String) and Other(Box<dyn Error>) catch-all variants from TaskError, replacing all usages with typed error variants. Also addresses all unresolved review comments from PR #739.

TaskError variant removal

  • Remove Generic(String) and Other(Box<dyn Error + Send + Sync>) from the enum
  • From<String> bridge now maps to LegacyError(s) as a temporary bridge for ~300 remaining Result<_, String> callsites — UserInput is reserved exclusively for actual user input validation errors
  • Update test that matched on TaskError::Generic

New specialized variants

Variant Replaces
SerializationError { detail } Generic(e.to_string()) for bincode
IdentifierParsingError { input } Generic(format!("Identifier error: ..."))
IdentityCreationError { source: Box<ProtocolError> } Generic(format!("Failed to create identity: ..."))
InvalidPrivateKey { detail } Generic("Voting private key is not valid")
DpnsFetchError { source: Box<SdkError> } Generic(format!("Error fetching DPNS names: ..."))
AssetLockNotValidForWallet Generic("Asset Lock not valid for wallet")
AssetLockInstantLockExpiredNotChainlocked from("Cannot use this asset lock...")
PlatformFetchError { source: Box<SdkError> } from(format!("Failed to fetch address info..."))
DashCoreStartError { source: std::io::Error } UserInput(e.to_string()) for start_dash_qt I/O failures
OperationNotAvailableOnNetwork { operation, allowed_networks } UserInput("Mining is only available...") for network restrictions
LegacyError(String) Generic(String) — temporary bridge for From<String> callers

PR 739 review comment fixes

  • Lock poisoning: Propagate TaskError::LockPoisoned instead of silently spinning (transaction_processing.rs) or dropping (load_identity.rs, load_identity_by_dpns_name.rs)
  • Wallet removal atomicity: Acquire write lock before DB deletion; change return type from Result<(), String> to Result<(), TaskError> (contract_token_db.rs)
  • Token update atomicity: Remove redundant remove_token before insert_tokeninsert_token already uses ON CONFLICT DO UPDATE upsert
  • Proof-log failures: log_drive_proof_error now tracing::warn! with context instead of let _ =
  • Instant-lock fallback regression: Match on format!("{:?}", e) (Debug) instead of e.to_string() (Display), since Display now returns user-friendly text that won't contain raw SDK error strings
  • Domain jargon: Rewrite AssetLockExpired, AssetLockAddressNotFound, AssetLockTransactionNotFoundInDatabase, AssetLockNoCreditOutputs display messages to avoid "asset lock", "instant lock", "Platform", "Core block"
  • Platform address identity creation: Use log_drive_proof_error instead of inline format!() for proof errors in register_identity_from_platform_addresses
Original prompt

remove TaskError::Generic and Task Error::Other variants. Replace all references with specialized variants. When done, commit and push. Then check all unresolved PR 739 review comments and address them. Commit and push afterwards.


📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

Copilot AI and others added 3 commits March 12, 2026 23:53
…ized variants

- Remove Generic(String) and Other(Box<dyn Error>) variants from TaskError
- Add SerializationError, IdentifierParsingError, IdentityCreationError,
  InvalidPrivateKey, DpnsFetchError, AssetLockNotValidForWallet,
  AssetLockInstantLockExpiredNotChainlocked, PlatformFetchError variants
- Update From<String> bridge to map to UserInput instead of Generic
- Replace TaskError::Generic("Identity not found") with IdentityNotFoundLocally
- Replace TaskError::Generic("Contract not found") with DataContractNotFound
- Replace TaskError::Generic(e.to_string()) for bincode with SerializationError
- Fix instant-lock fallback to use Debug repr instead of Display for string matching
- Fix poisoned lock spinning in transaction_processing.rs
- Fix silently dropped wallet locks in load_identity.rs and load_identity_by_dpns_name.rs
- Change contract_token_db::remove_wallet to return TaskError instead of String
- Use typed variants in register_identity.rs and top_up_identity.rs
- Use ? operator for lock errors in core/mod.rs

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
- Fix wallet removal atomicity: acquire write lock before DB removal
- Fix proof-log write failures: warn instead of silently dropping
- Fix domain jargon in AssetLock* error messages (no "asset lock", "instant lock")
- Fix token metadata update atomicity: use upsert instead of remove+insert

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
…dd TODO notes

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Copilot AI changed the title [WIP] Remove TaskError::Generic and TaskError::Other variants refactor: remove TaskError::Generic and TaskError::Other, replace with specialized variants Mar 13, 2026
Copilot AI requested a review from lklimek March 13, 2026 00:06
Comment thread src/backend_task/core/mod.rs Outdated
CoreTask::StartDashQT(network, custom_dash_qt, overwrite_dash_conf) => self
.start_dash_qt(network, custom_dash_qt, overwrite_dash_conf)
.map_err(|e| TaskError::from(e.to_string()))
.map_err(|e| TaskError::UserInput(e.to_string()))
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.

@copilot the task is to define new granular variants in TaskError that will describe each error condition as close as possible. Don't use any catch all of generalized existing variants of they are not a perfect fit for the situation. Apply this comment to whole PR. - check context of change and select or create variant that is close match to the situation, and has the same expected user action. Refer to CLAUDE.md for guidelines.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Applied across the whole PR in b7d5fc6 and c574744:

  • start_dash_qt io::Error → new DashCoreStartError { source: std::io::Error } (preserves source chain)
  • Mining network restriction → new OperationNotAvailableOnNetwork { operation, allowed_networks } (structured fields for the specific condition)
  • From<String> bridge now maps to LegacyError(String) instead of UserInputUserInput is reserved exclusively for actual user input validation errors
  • All other changes in the PR already used granular variants (IdentifierParsingError, InvalidPrivateKey, DpnsFetchError, AssetLockNotValidForWallet, etc.)

Copilot AI and others added 2 commits March 13, 2026 06:10
…r, OperationNotAvailableOnNetwork, and LegacyError variants

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
…tAvailableOnNetwork display

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 13, 2026

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • 8.8.4.4
    • Triggering command: REDACTED, pid is -1 (packet block)
  • 8.8.8.8
    • Triggering command: REDACTED, pid is -1 (packet block)
  • example.com
    • Triggering command: /home/REDACTED/work/dash-evo-tool/dash-evo-tool/target/debug/deps/dash_evo_tool-3cc460801310ec10 /home/REDACTED/work/dash-evo-tool/dash-evo-tool/target/debug/deps/dash_evo_tool-3cc460801310ec10 --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=line-tables-only c460801310ec10.02mkjijwpqev195sxxnyhpq0o.0h9opmu.rcgu.o c460801310ec10.048hme6gpaqpjyb5e4hgg0gcq.0h9opmu.rcgu.o c460801310ec10.07hp8y9kl8c7z9rou6ws3d9ht.0h9opmu.rcgu.o c460801310ec10.07laog3lofpaphjgzgarry0d8.0h9opmu.rcgu.o c460801310ec10.088460fx7ulv0txyopw9eu6mf.0h9opmu.rcgu.o c460801310ec10.0euye8wv4z9974fvxof3hh6wr.0h9opmu.rcgu.o c460801310ec10.0j3rnbiwg1fm3iwy7nb8urnx5.0h9opmu.rcgu.o c460801310ec10.0l5xteefz1396vuba4i59sbto.0h9opmu.rcgu.o c460801310ec10.0nastitmdrlhzrmzpkmdzd8d8.0h9opmu.rcgu.o c460801310ec10.0nbybmt4rg1b4iaeqzgu0f10a.0h9opmu.rcgu.o c460801310ec10.0ng1utedv9y2ostxs1kc09xqo.0h9opmu.rcgu.o c460801310ec10.0q521560svd0pzuavx1b6pev9.0h9opmu.rcgu.o c460801310ec10.0quaak0c430fsby6xrwygkvaa.0h9opmu.rcgu.o c460801310ec10.0t1n8ycrf9vedxd4m26b3vqow.0h9opmu.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/dash-evo-tool/dash-evo-tool/target/debug/deps/dash_evo_tool-3cc460801310ec10 /home/REDACTED/work/dash-evo-tool/dash-evo-tool/target/debug/deps/dash_evo_tool-3cc460801310ec10 -C embed-bitcode=no -REDACTED-linux-gnu/bin/rust-lld debuginfo=2 --allow=clippy::uninlined_format_args --warn=unexpected_cfgs --check-cfg cfg(tokio_unstable) --check-cfg cfg(feature, values(&#34;testing&#34;)) --test kitt�� kittest-9858595cd197a41d.1ue5dikcmierj3p38lthio63j.1olooc2.rcgu.o kittest-9858595cd197a41d.1wv0h3o42xstyaviuby9yyz0t.1olooc2.rcgu.o -1949cf8c6b5b557f/zmq-0.10.0/src-m 22-ws_decoder.o -incompat 22-ws_engine.o 1.92-x86_64-unkndash_evo_tool (dns block)
  • invalid.domain.that.does.not.exist.test
    • Triggering command: /home/REDACTED/work/dash-evo-tool/dash-evo-tool/target/debug/deps/dash_evo_tool-3cc460801310ec10 /home/REDACTED/work/dash-evo-tool/dash-evo-tool/target/debug/deps/dash_evo_tool-3cc460801310ec10 --emit=dep-info,metadata,link -C embed-bitcode=no -C debuginfo=line-tables-only c460801310ec10.02mkjijwpqev195sxxnyhpq0o.0h9opmu.rcgu.o c460801310ec10.048hme6gpaqpjyb5e4hgg0gcq.0h9opmu.rcgu.o c460801310ec10.07hp8y9kl8c7z9rou6ws3d9ht.0h9opmu.rcgu.o c460801310ec10.07laog3lofpaphjgzgarry0d8.0h9opmu.rcgu.o c460801310ec10.088460fx7ulv0txyopw9eu6mf.0h9opmu.rcgu.o c460801310ec10.0euye8wv4z9974fvxof3hh6wr.0h9opmu.rcgu.o c460801310ec10.0j3rnbiwg1fm3iwy7nb8urnx5.0h9opmu.rcgu.o c460801310ec10.0l5xteefz1396vuba4i59sbto.0h9opmu.rcgu.o c460801310ec10.0nastitmdrlhzrmzpkmdzd8d8.0h9opmu.rcgu.o c460801310ec10.0nbybmt4rg1b4iaeqzgu0f10a.0h9opmu.rcgu.o c460801310ec10.0ng1utedv9y2ostxs1kc09xqo.0h9opmu.rcgu.o c460801310ec10.0q521560svd0pzuavx1b6pev9.0h9opmu.rcgu.o c460801310ec10.0quaak0c430fsby6xrwygkvaa.0h9opmu.rcgu.o c460801310ec10.0t1n8ycrf9vedxd4m26b3vqow.0h9opmu.rcgu.o (dns block)
    • Triggering command: /home/REDACTED/work/dash-evo-tool/dash-evo-tool/target/debug/deps/dash_evo_tool-3cc460801310ec10 /home/REDACTED/work/dash-evo-tool/dash-evo-tool/target/debug/deps/dash_evo_tool-3cc460801310ec10 -C embed-bitcode=no -REDACTED-linux-gnu/bin/rust-lld debuginfo=2 --allow=clippy::uninlined_format_args --warn=unexpected_cfgs --check-cfg cfg(tokio_unstable) --check-cfg cfg(feature, values(&#34;testing&#34;)) --test kitt�� kittest-9858595cd197a41d.1ue5dikcmierj3p38lthio63j.1olooc2.rcgu.o kittest-9858595cd197a41d.1wv0h3o42xstyaviuby9yyz0t.1olooc2.rcgu.o -1949cf8c6b5b557f/zmq-0.10.0/src-m 22-ws_decoder.o -incompat 22-ws_engine.o 1.92-x86_64-unkndash_evo_tool (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from lklimek March 13, 2026 06:14
@lklimek lklimek marked this pull request as ready for review March 13, 2026 06:39
@lklimek lklimek merged commit d44ade4 into task/660-i18n-ready-strings-general-rule Mar 13, 2026
2 checks passed
@lklimek lklimek deleted the copilot/remove-generic-task-errors branch March 13, 2026 06:39
lklimek added a commit that referenced this pull request Mar 15, 2026
)

* docs: promote i18n-ready strings to general coding rule (#660)

Move the i18n guideline out of the error-messages section into general
rules, broadening its scope to all user-facing strings (labels, tooltips,
messages). Remove direct Fluent reference, fix placeholder syntax to
Rust-style `{ name }`, and renumber remaining error rules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: add typed error variants for migration (#660)

Add new TaskError variants (LockPoisoned, Database, CoreRpc, P2P),
new domain error types (P2PError, WalletError::KeyDerivation,
WalletError::Sighash, DashPayError::QueryCreation,
DashPayError::CryptoKeyParsing, DashPayError::PrivateKeyResolution,
ConfigError::SaveError), and replace the transparent Sqlite variant
with a user-friendly Database variant.

Drop Clone/PartialEq from DashPayError to support #[source] fields
and fix the two downstream callsites that depended on them.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: replace string errors with typed errors in spv/config/infra (#660)

- core_p2p_handler: eliminate ReadMessageError(String), use P2PError variants
  throughout internal methods; keep public API returning String for callers
  outside scope
- config: replace ConfigError::LoadError with SaveError in save() for all
  I/O operations (writeln, sync_all, persist)
- backend_task/mod: add map_err(TaskError::from) bridges for wallet task
  functions that still return String
- model/wallet: fix KeyDerivation source type mismatch (key_wallet::Error !=
  bip32::Error) by reverting to e.to_string() at derivation_path() callsites

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: replace string errors with typed TaskError in model/database/context (#660)

- Use WalletError::AddressError in utxos.rs for dashcore address errors
- Use TaskError::from(e) for RPC errors in broadcast_raw_transaction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: replace string errors with typed TaskError in backend_task/ (#660)

Migrate callsites in src/backend_task/ from Result<T, String> to
Result<T, TaskError>:

- broadcast_state_transition: map SDK error via TaskError::from
- contract: direct ? for rusqlite, TaskError::from for SDK errors
- document: all 7 document operations migrated
- mod.rs: run_wallet_task return type updated to TaskError
- register_contract: sender error → InternalSendError, SDK → TaskError::from
- update_data_contract: sender error → InternalSendError, format strings → Generic
- wallet/*: lock poison → Generic, SDK errors → TaskError::from, ? for rusqlite

Build, clippy, and fmt all pass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: replace string errors with typed TaskError in ui/ (#660)

Migrate rusqlite error callsites in src/ui/ to typed TaskError variants:

- `IdentityTokenInfo::try_from_*` functions in tokens_screen/structs.rs
  now return `Result<Self, TaskError>` — DB errors become
  `TaskError::Database` via `?` instead of `.map_err(|e| e.to_string())`.
  Callers use `MessageBanner::set_global` with the error which accepts
  `impl Display`, so no caller changes were needed.

- `save_private_info` in contact_profile_viewer.rs now returns
  `Result<(), TaskError>` — the rusqlite error is wrapped explicitly
  as `TaskError::Database { source: e }` for clear error semantics.

All other `map_err(|e| e.to_string())` callsites in src/ui/ were
reviewed and left unchanged — they are in UI-local validation functions
(clipboard, form validation, address generation) that do not feed into
the backend task error system.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: remove useless TaskError::from conversions in wallet task dispatch (#660)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: fix all unresolved review comments — proof errors, asset lock, format! migrations (#740)

* Initial plan

* refactor: add typed TaskError variants, eliminate Generic from backend_task files

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: eliminate Result<T,String> from context/transaction_processing, add typed TaskError variants

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: migrate context/wallet_lifecycle.rs from Result<T,String> to Result<T,TaskError>

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: add source_error to ProofError, add log_drive_proof_error helper, migrate token tasks to TaskError

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: replace TaskError::Internal with granular variants, migrate identity tasks to TaskError

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* style: apply cargo +nightly fmt to fix CI formatting failures

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: fix all unresolved review comments (Claude + lklimek)

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: remove TaskError::Generic and TaskError::Other, replace with specialized variants (#744)

* Initial plan

* refactor: remove TaskError::Generic and TaskError::Other, add specialized variants

- Remove Generic(String) and Other(Box<dyn Error>) variants from TaskError
- Add SerializationError, IdentifierParsingError, IdentityCreationError,
  InvalidPrivateKey, DpnsFetchError, AssetLockNotValidForWallet,
  AssetLockInstantLockExpiredNotChainlocked, PlatformFetchError variants
- Update From<String> bridge to map to UserInput instead of Generic
- Replace TaskError::Generic("Identity not found") with IdentityNotFoundLocally
- Replace TaskError::Generic("Contract not found") with DataContractNotFound
- Replace TaskError::Generic(e.to_string()) for bincode with SerializationError
- Fix instant-lock fallback to use Debug repr instead of Display for string matching
- Fix poisoned lock spinning in transaction_processing.rs
- Fix silently dropped wallet locks in load_identity.rs and load_identity_by_dpns_name.rs
- Change contract_token_db::remove_wallet to return TaskError instead of String
- Use typed variants in register_identity.rs and top_up_identity.rs
- Use ? operator for lock errors in core/mod.rs

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: address remaining PR 739 review comments

- Fix wallet removal atomicity: acquire write lock before DB removal
- Fix proof-log write failures: warn instead of silently dropping
- Fix domain jargon in AssetLock* error messages (no "asset lock", "instant lock")
- Fix token metadata update atomicity: use upsert instead of remove+insert

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: address code review comments - improve error messages and add TODO notes

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: replace UserInput catch-all with granular DashCoreStartError, OperationNotAvailableOnNetwork, and LegacyError variants

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: improve DashCoreStartError message and simplify OperationNotAvailableOnNetwork display

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: address PR #739 review comments — structural error matching, lock poisoning cleanup, parameterized RequestType

- Parameterize `log_drive_proof_error` with `RequestType` instead of hardcoding `BroadcastStateTransition` (26 callsites across 15 files)
- Replace all `map_err` to `LockPoisoned` with `?` operator using blanket `From<PoisonError<T>>` impl; add doc comment explaining the intentional design
- Change `CreditCalculationOverflow` variant to carry raw data fields (`amount`, `credits_per_duff`) instead of pre-formatted text
- Add `TaskError::AssetLockInstantLockProofInvalid` variant with structural SDK error matching, replacing fragile `format!("{:?}").contains(...)` in register_identity and top_up_identity
- Replace `StaleNode` string matching with structural `Error::StaleNode(_)` match in contested names queries
- Add `is_unique_constraint_violation()` helper for SQLite error matching in import_mnemonic_screen
- Fix wrong error variant: `DocumentNotFound` → `DataContractNotFound` in update_token_config
- Add TODO for `BroadcastError(String)` pending `ScreenLike::display_message` trait redesign

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: address remaining PR #739 review comments — lock poisoning, error interpolation, StaleNode matching

- Remove all remaining explicit `map_err` to `LockPoisoned` across 10 files, using `?` with blanket `From<PoisonError<T>>` impl
- Fix `context/mod.rs` sites returning `Result<_, String>` to use `TaskError::from(e).to_string()` instead of discarding resource info
- Add `StaleNode` structural matching to `query_dpns_vote_contenders.rs` for consistency with `query_dpns_contested_resources.rs`
- Interpolate `operation` and `allowed_networks` fields in `OperationNotAvailableOnNetwork` error message
- Narrow `is_unique_constraint_violation` to check `extended_code: 2067` (SQLITE_CONSTRAINT_UNIQUE)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: address final PR #739 review comments — jargon removal, dual signal fix

- Replace protocol jargon ("asset lock", "instant lock proof",
  "chain lock proof") with user-friendly language in three
  TaskError Display messages per CLAUDE.md error guidelines
- Fix dual success+error signal in register_contract.rs: return
  Ok(ContractSavedAfterProofError) instead of sending success
  via channel then returning Err(ProofError)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: add 6 new TaskError variants for LegacyError removal

Add PlatformInfoFetchError, EncryptionError, WalletDatabasePersistError,
AvatarProcessingError, MasterKeyNotFound, and TokenQueryError variants
to prepare for removing From<String> and LegacyError.

Also fix test assertion for updated jargon-free error message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: migrate system/grovestark/mnlist/platform_info to TaskError

Replace Result<_, String> with Result<_, TaskError> in four domain
dispatcher modules, eliminating reliance on From<String> for TaskError
in these paths.

- system_task: use ? on rusqlite errors (via #[from])
- grovestark: use ? on GroveSTARKError (via #[from])
- mnlist: replace .unwrap() on RwLock with proper error handling
- platform_info: wrap SDK errors in TaskError::SdkError, use
  TaskError::Generic for document property extraction errors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: remove From<String> for TaskError and LegacyError variant

Remove the `impl From<String> for TaskError` bridge and `TaskError::LegacyError(String)`
variant. All 45 files that relied on string-to-TaskError conversion now use typed variants.

Migration patterns applied:
- RwLock/Mutex `.map_err(|e| e.to_string())?` → bare `?` (From<PoisonError>)
- rusqlite `.map_err(|e| e.to_string())?` → bare `?` (Database #[from])
- dashcore_rpc errors → bare `?` (From<dashcore_rpc::Error>)
- SDK errors → bare `?` (From<SdkError>)
- String literals → typed variants (UserInput, WalletNotFound, etc.)
- Model/SPV boundary → .map_err(TaskError::UserInput) at callsite

New variants used: PlatformInfoFetchError, EncryptionError,
WalletDatabasePersistError, AvatarProcessingError, MasterKeyNotFound,
TokenQueryError.

45 files changed, 859 insertions(+), 1000 deletions(-)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: address 16 review findings across error handling and conventions

Error design (error.rs):
- Remove dead AvatarProcessingError variant (CODE-004)
- Add ContractSchemaMismatch variant for contested index (CODE-006)
- Add WithdrawalDocumentParsingError variant for withdrawal parsing (CODE-007)
- Route 9 platform_info.rs callsites through From<SdkError> classification (CODE-001)

Correctness fixes:
- Fix dual signal in update_data_contract: return Ok instead of send+Err (CODE-002)
- Return Ok(None) instead of Err(QueryReturnedNoRows) in contract_token_db (CODE-003)

P2P module:
- Public API returns P2PError instead of String, enabling #[from] conversion (CODE-008)
- Add ProtocolError variant for protocol violations instead of synthetic io::Error (CODE-009)

Error message quality:
- Rewrite ~20 DashPayError Display messages for Everyday User audience (PROJ-001)
- Rewrite ConfigError::NoValidConfigs and WalletError::AddressError Display (PROJ-004)
- Update CLAUDE.md rule 7: remove stale Generic references (PROJ-002)
- Clarify i18n placeholder style in CLAUDE.md (PROJ-005)

Mechanical improvements:
- Replace explicit TaskError::Database{source:e} with ? via #[from] (CODE-010)
- Replace ok_or_else with ok_or for unit-like TaskError variants (CODE-011)
- Replace .unwrap() with .unwrap_or_else(|e| e.into_inner()) in identity_db (CODE-017)
- Simplify lock poisoning double-conversion in context/mod.rs (CODE-018)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: replace `UserInput(String)` with typed `TaskError` variants (#751)

* Initial plan

* refactor: replace all UserInput usages with typed TaskError variants

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: improve error message clarity (reviewer feedback)

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: merge RPC/context variants, split NotTokenDistributionRecipient, use #[source] for typed errors

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* refactor: address review feedback on TaskError migration — jargon, transparent errors, variant cleanup (#753)

* Initial plan

* refactor: address all review feedback — transparent errors, IdentitySaveError, DpnsFetchError, CLAUDE.md

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* fix: resolve CI formatting failures (#754)

* Initial plan

* fix: run cargo +nightly fmt --all to fix CI formatting failures

Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: lklimek <842586+lklimek@users.noreply.github.com>

* fix: address 3 PR review findings — error chain, transitional note, vote errors

- DashPayError::SdkError: preserve error chain with #[source] Box<dash_sdk::Error>
  instead of stringifying to reason: String
- CLAUDE.md rule 7: add transitional note acknowledging detail: String pattern
- vote_on_dpns_name: route SDK errors through TaskError for user-friendly messages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address review round 4 — typed errors, dead code, lock safety

- vote_on_dpns_name: use ContractSchemaMismatch instead of fake SdkError::Generic
- core/mod.rs: migrate 7 payment functions from Result<_, String> to Result<_, TaskError>
- load_identity_from_wallet: replace .unwrap() with ? on wallet RwLock operations
- Remove dead UiError type (src/ui/error.rs) — zero usages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: strengthen error variant policy — never use String fields for user messages

CLAUDE.md rule 7: replace transitional note with strict rule — error variants
must not contain String fields that hold user-facing messages. Use #[source]
with typed errors, or fieldless variants. Replace existing String-field variants
when encountered.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
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