Add error code descriptions as code comments#3209
Conversation
|
Claude finished @jhaaaa's task —— View job PR Review - Error Code DocumentationDate: March 4, 2026 at 02:06 UTC SummaryThis PR adds comprehensive error documentation with compile-time enforcement. The implementation is solid with good architectural decisions. The author has already addressed most substantive feedback from macroscopeapp. Code Quality: ✅ ExcellentDerive Macro Implementation (
Error Glossary Tool (
CI Workflow (
Potential Issues: None Critical
Performance: ✅ Good
Security: ✅ No Concerns
Test Coverage: 📊 As ExpectedThe 3.66% patch coverage is appropriate - this is documentation tooling that:
Adding tests would be valuable for future maintenance but is not a blocker. Architecture: ✅ Well Designed
RecommendationsNon-blocking improvements:
Overall Assessment: Ready to merge. This is well-executed documentation infrastructure with thoughtful design decisions. The compile-time enforcement ensures long-term maintainability. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3209 +/- ##
==========================================
- Coverage 72.61% 72.30% -0.31%
==========================================
Files 479 483 +4
Lines 59161 59506 +345
==========================================
+ Hits 42958 43027 +69
- Misses 16203 16479 +276 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
… jh/error-code-comments
| MemberNotAllowed(MemberKind, MemberKind), | ||
| /// Missing existing member. | ||
| /// | ||
| /// Required signer not found or signer identity mismatch. Not retryable. |
There was a problem hiding this comment.
We wrote: “Required signer not found or signer identity mismatch.” The code checks both that the signer exists in the state and that the signer’s identifier matches the expected member. A domain expert may want more precise wording.
| MissingExistingMember, | ||
| /// Legacy signature reuse. | ||
| /// | ||
| /// Legacy delegated signature used in disallowed context. Not retryable. |
There was a problem hiding this comment.
We wrote: “Legacy delegated signature used in disallowed context.” The actual rule is nuanced: legacy delegated signatures can only appear on CreateInbox actions with nonce 0. Someone familiar with the identity protocol should confirm the description captures the intent.
| InvalidHash, | ||
| /// Unspecified value. | ||
| /// | ||
| /// An unrecognized or unsupported value was encountered. Not retryable. |
There was a problem hiding this comment.
We wrote: “An unrecognized or unsupported value was encountered.” This is used for proto enum fields that deserialize to the UNSPECIFIED (0) variant. A domain expert may want to say something more specific about protobuf zero-values.
| /// Malformed chain ID. | ||
| /// | ||
| /// Chain ID string lacks expected eip155: prefix. Not retryable. | ||
| #[error("Chain IDs must be preceded with eip155:")] |
There was a problem hiding this comment.
We renamed the description from “URL” to “Chain ID” and fixed eip144 → eip155. The variant name still says Url, but the actual check is about the eip155: prefix on chain ID strings. Someone may want to rename the variant itself for clarity (with #[error_code("VerifierError::MalformedEipUrl")] to preserve the code).
| Signature(#[from] SignatureError), | ||
| /// Unable to get block number. | ||
| /// | ||
| /// Block number not returned after successful SCW verification. May be retryable. |
There was a problem hiding this comment.
We wrote: “Block number not returned after successful SCW verification.” The code performs SCW verification, then calls get_block_number(), and errors if it returns None. A domain expert should confirm whether “after successful SCW verification” is the right framing.
|
Regarding Findings: 1 - Panic in main.rs: Not an issue. canonicalize() failing is the 2 - Doc comment whitespace: They answered their own question — it 3 - Missing test coverage: Same feedback as before. Valid 4 - Workflow trigger efficiency: They also answered their own 5 - Error code format not enforced: This is intentional. Custom 6 - Silent filtering of internal types: Decent idea but low |
| @@ -0,0 +1,568 @@ | |||
| <!-- This file is auto-generated by error_glossary. Do not edit manually. --> | |||
There was a problem hiding this comment.
Wow. Having all of these in one place is a thing of beauty. ❤️
Dismissing my prior approval and re-evaluating approvability for 3957f5d
There was a problem hiding this comment.
This PR adds documentation comments to error types throughout the codebase and creates a tool to generate an error glossary. All changes to source files are purely /// doc comments with no runtime impact. The new error_glossary app is a dev tool only, and the proc macro changes are additive compile-time checks. This is a documentation-only change.
3e55860 to
0f5bcda
Compare
Dismissing my prior approval and re-evaluating approvability for 0f5bcda
There was a problem hiding this comment.
This PR adds documentation comments to error enum variants throughout the codebase and adds compile-time enforcement that such comments exist. These are purely documentation changes with no runtime behavior impact - doc comments in Rust don't affect the compiled code. Safe to approve.
Dismissing prior approval to re-evaluate fd5bbf7
ApprovabilityVerdict: Approved This PR adds documentation comments to error types across the codebase and introduces tooling to auto-generate an error glossary. All changes to source files are purely additive doc comments that don't affect runtime behavior. The open review comments are author-flagged suggestions for domain expert review on wording, not blocking concerns. You can customize Macroscope's approvability policy. Learn more. |
72432f5 to
0840e82
Compare
Dismissing prior approval to re-evaluate 0840e82
Dismissing prior approval to re-evaluate 1839868
cameronvoell
left a comment
There was a problem hiding this comment.
excited to try this out! I think this recommendation from Claude would be a nice next step to make sure this stays well maintained moving forward:
Consider adding integration tests for the glossary tool (parse sample error files, verify output)
great work!
## Summary Restores the `--release` flag to `just wasm test-v3` and `just wasm test-d14n`, which was accidentally dropped in #3307. ## Background Three commits tell the story of how we got here: | PR | Change | Effect | |---|---|---| | Before #3235 | `cargo test --locked --release --target wasm32-unknown-unknown` | Baseline (fast) | | #3235 "Improve WASM test speed" | Switched to `cargo nextest run` | Actually much slower (see below) | | #3307 "update rust to 1.94" | Reverted nextest → `cargo test`, but **dropped `--release`** | Current state (slow) | ## Why nextest is wrong for WASM tests `cargo nextest` runs each **individual test case in its own subprocess**. For WASM tests, the subprocess runner is `wasm-bindgen-test-runner` (configured in `.cargo/config.toml`). Every subprocess invocation: 1. Starts ChromeDriver 2. Launches a headless Chrome instance 3. Loads the WASM binary into Chrome 4. Runs **one test** 5. Shuts down Chrome With `cargo test`, all tests in a package binary share a single Chrome instance — about 7 Chrome startups total (one per package in `wasm_packages`). With nextest, you get **one Chrome startup per test case** — potentially 500+ Chrome startups for the same test suite. **`cargo test` is the correct tool for WASM targets. This PR keeps it.** ## Root cause of current slowness: missing `--release` Without `--release`, WASM test binaries compile in debug mode. This is significantly slower for several reasons: **Binary size.** Debug WASM binaries are 5–20x larger than release binaries. Chrome must parse and JIT-compile the entire WASM module before running any test. With a large debug binary, this startup cost dominates. **Execution speed.** The `test` profile in `.cargo/config.toml` optimizes *dependencies* at `opt-level = 3`: ```toml [profile.test] package."*" = { opt-level = 3, ... } # dependencies only ``` But workspace crates themselves still compile at `opt-level = 0`. This means the MLS crypto code (OpenMLS, SHA, AES-GCM), the SQLite ORM layer, and all other first-party code runs completely unoptimized. These operations are the bulk of what the tests exercise. **The fix** is a two-character addition to each test command in `wasm.just`: ```diff - cargo test --locked --target wasm32-unknown-unknown \ + cargo test --locked --release --target wasm32-unknown-unknown \ ``` ## Test plan - [x] WASM unit tests pass (`just wasm test`) - [ ] WASM integration tests pass (`just wasm test-integration`) - [x] Compare CI timing against recent runs on `main` to confirm improvement ## Results CI run: https://github.com/xmtp/libxmtp/actions/runs/22979506469 ### Test (WASM) job timing | Run | Commit | WASM job time | sccache hit rate | |---|---|---|---| | **This PR** | Restore `--release` | **17m30s** | **0% (cold — first release-mode run)** | | main #3315 | Fix flaky tests | 14m46s | 78% (702 hits / 195 misses) | | main #3209 | Add error code descriptions | 22m32s | — | | main #3170 | Add proposal support | 19m30s | — | | main (prior) | Remove associated types | 19m39s | — | ### Analysis This PR completed in **17m30s with a completely cold sccache** (0 hits, 0 misses — the cache contains no release-mode artifacts yet). Despite the cold cache penalty, it is already faster than 3 of the 4 recent `main` runs. The fastest recent `main` run (14m46s) had a **78% cache hit rate** with 702 hits. Once the release-mode sccache warms up on subsequent runs, this PRs steady-state time should be well under 14m46s, since: 1. The compiled release artifacts will be cached by sccache 2. Release WASM binaries are significantly smaller than debug, so Chrome parse/JIT time is faster 3. Test execution itself is faster in release mode (optimized MLS crypto, SQLite ORM, etc.) **Expected steady-state improvement vs. current `main`: ~20-30% faster** once cache is warm, in addition to faster per-test execution time in Chrome.
## Summary Restores the `--release` flag to `just wasm test-v3` and `just wasm test-d14n`, which was accidentally dropped in #3307. ## Background Three commits tell the story of how we got here: | PR | Change | Effect | |---|---|---| | Before #3235 | `cargo test --locked --release --target wasm32-unknown-unknown` | Baseline (fast) | | #3235 "Improve WASM test speed" | Switched to `cargo nextest run` | Actually much slower (see below) | | #3307 "update rust to 1.94" | Reverted nextest → `cargo test`, but **dropped `--release`** | Current state (slow) | ## Why nextest is wrong for WASM tests `cargo nextest` runs each **individual test case in its own subprocess**. For WASM tests, the subprocess runner is `wasm-bindgen-test-runner` (configured in `.cargo/config.toml`). Every subprocess invocation: 1. Starts ChromeDriver 2. Launches a headless Chrome instance 3. Loads the WASM binary into Chrome 4. Runs **one test** 5. Shuts down Chrome With `cargo test`, all tests in a package binary share a single Chrome instance — about 7 Chrome startups total (one per package in `wasm_packages`). With nextest, you get **one Chrome startup per test case** — potentially 500+ Chrome startups for the same test suite. **`cargo test` is the correct tool for WASM targets. This PR keeps it.** ## Root cause of current slowness: missing `--release` Without `--release`, WASM test binaries compile in debug mode. This is significantly slower for several reasons: **Binary size.** Debug WASM binaries are 5–20x larger than release binaries. Chrome must parse and JIT-compile the entire WASM module before running any test. With a large debug binary, this startup cost dominates. **Execution speed.** The `test` profile in `.cargo/config.toml` optimizes *dependencies* at `opt-level = 3`: ```toml [profile.test] package."*" = { opt-level = 3, ... } # dependencies only ``` But workspace crates themselves still compile at `opt-level = 0`. This means the MLS crypto code (OpenMLS, SHA, AES-GCM), the SQLite ORM layer, and all other first-party code runs completely unoptimized. These operations are the bulk of what the tests exercise. **The fix** is a two-character addition to each test command in `wasm.just`: ```diff - cargo test --locked --target wasm32-unknown-unknown \ + cargo test --locked --release --target wasm32-unknown-unknown \ ``` ## Test plan - [x] WASM unit tests pass (`just wasm test`) - [ ] WASM integration tests pass (`just wasm test-integration`) - [x] Compare CI timing against recent runs on `main` to confirm improvement ## Results CI run: https://github.com/xmtp/libxmtp/actions/runs/22979506469 ### Test (WASM) job timing | Run | Commit | WASM job time | sccache hit rate | |---|---|---|---| | **This PR** | Restore `--release` | **17m30s** | **0% (cold — first release-mode run)** | | main #3315 | Fix flaky tests | 14m46s | 78% (702 hits / 195 misses) | | main #3209 | Add error code descriptions | 22m32s | — | | main #3170 | Add proposal support | 19m30s | — | | main (prior) | Remove associated types | 19m39s | — | ### Analysis This PR completed in **17m30s with a completely cold sccache** (0 hits, 0 misses — the cache contains no release-mode artifacts yet). Despite the cold cache penalty, it is already faster than 3 of the 4 recent `main` runs. The fastest recent `main` run (14m46s) had a **78% cache hit rate** with 702 hits. Once the release-mode sccache warms up on subsequent runs, this PRs steady-state time should be well under 14m46s, since: 1. The compiled release artifacts will be cached by sccache 2. Release WASM binaries are significantly smaller than debug, so Chrome parse/JIT time is faster 3. Test execution itself is faster in release mode (optimized MLS crypto, SQLite ORM, etc.) **Expected steady-state improvement vs. current `main`: ~20-30% faster** once cache is warm, in addition to faster per-test execution time in Chrome.
This PR:
///doc comments to all ~327 error variants that deriveErrorCode, describing what each error means and its retryability.ErrorCodederive macro now enforces doc comments at compile time. A missing comment will result in a build error.#[error_code(internal)]attribute to mark error types that are not reachable from SDK bindings. These errors will not be included in the error_glossary.apps/error_glossary/, a tool that parses the source and generatesdocs/error_glossary.mdwith all public error codes.docs/error-architecture.mdexplaining how the error code system works and how to add new codes.Regarding the accuracy of the error code descriptions, Claude Code said it is "99% confident on technical accuracy for the descriptions outside of the 5 flagged items." You can see these flagged items marked by comments in the diff view. This is what Claude Code did to ensure error code description accuracy:
Note
Add error code glossary generator and doc comments across all error enums
error_glossarybinary app (apps/error_glossary/) that walks the workspace, parses Rust source files withsyn, and generates a markdown glossary of allErrorCode-deriving types with descriptions and retryability notes.derive_error_codeproc macro in crates/xmtp_macro/src/lib.rs to enforce doc comments on non-remote types and support new attributes:inherit,internal, andremote = "path::Type".NotFound::IntentForToPublishnow says "Published" instead of "Publish", andVerifierError::MalformedEipUrlnow says "eip155" instead of "eip144".Changes since #3209 opened
error_codederive macro to enforce doc comment requirements and support internal attribute [1839868]xmtp_api_d14nandxmtp_mlscrates [1839868]xmtp-workspace-hackpackage [350d5ef]📊 Macroscope summarized 0840e82. 36 files reviewed, 2 issues evaluated, 0 issues filtered, 2 comments posted
🗂️ Filtered Issues