Skip to content

refactor(l1): improve error handling in set_sync_block with eyre::Result#6465

Open
emirongrr wants to merge 7 commits intolambdaclass:mainfrom
emirongrr:refactor/sync-block-error-handling
Open

refactor(l1): improve error handling in set_sync_block with eyre::Result#6465
emirongrr wants to merge 7 commits intolambdaclass:mainfrom
emirongrr:refactor/sync-block-error-handling

Conversation

@emirongrr
Copy link
Copy Markdown
Contributor

@emirongrr emirongrr commented Apr 10, 2026

Motivation

The current set_sync_block() function uses identical error messages for two different failure
scenarios (store query failure vs. hash not found), making it impossible to distinguish which
layer failed. Using eyre::Result with distinct error contexts for each failure point provides
better diagnostics and aligns with the codebase's error handling standard.

Description

Refactored set_sync_block() function in cmd/ethrex/initializers.rs to use eyre::Result<()>
error handling instead of .expect() calls:

  • Changed function from async fn() to async fn() -> eyre::Result<()>
  • Replaced .expect() with explicit error handling using wrap_err() and ok_or_else()
  • Added distinct error messages for each failure point:
  • Updated init_l1() to propagate errors with ? operator

Note

If this refactoring is considered excessive or unnecessary, feel free to reject or close this PR.
A simpler alternative would be to just fix the duplicate error messages:

.expect("Failed to query block hash from store")
.expect("Block hash not found for block number {block_number}");

Checklist

  • Updated STORE_SCHEMA_VERSION (crates/storage/lib.rs) if the PR includes breaking changes to the Store requiring a re-sync.

@emirongrr emirongrr requested a review from a team as a code owner April 10, 2026 20:05
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 10, 2026

Greptile Summary

This PR refactors set_sync_block (guarded by #[cfg(feature = \"sync-test\")]) to return eyre::Result<()> with distinct error messages instead of identical .expect() calls — a good motivation. However, it introduces a behavioral regression: the original code wrapped the whole function body in if let Ok(...) = env::var(\"SYNC_BLOCK_NUM\") so that a missing variable was a silent no-op; the new code uses env::var(...)?, which converts VarError::NotPresent into an error that propagates through init_l1 and crashes startup for every node that doesn't set this env var.

Confidence Score: 2/5

Not safe to merge — drops the optional env-var guard, breaking node startup when SYNC_BLOCK_NUM is unset.

The single changed function contains a P0 behavioral regression: any node running without the SYNC_BLOCK_NUM env var will now fail to initialize.

cmd/ethrex/initializers.rs — specifically the env::var call at line 465 that must restore the optional guard.

Important Files Changed

Filename Overview
cmd/ethrex/initializers.rs Refactors set_sync_block to return eyre::Result<()>, but drops the if let Ok guard, making a missing SYNC_BLOCK_NUM env var propagate as an error and crash init_l1.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["init_l1()"] --> B["#[cfg(feature = sync-test)] set_sync_block()"]
    B --> C{"env::var('SYNC_BLOCK_NUM')"}
    C -- "Err(NotPresent)\n[OLD: silent no-op]\n[NEW: propagates error ❌]" --> D["return Ok(()) [OLD]\nreturn Err → init_l1 fails [NEW]"]
    C -- "Ok(value)" --> E["parse as u64"]
    E -- "parse error" --> F["eyre error → init_l1 fails"]
    E -- "ok" --> G["store.get_canonical_block_hash()"]
    G -- "store error" --> H["eyre error → init_l1 fails"]
    G -- "None" --> I["eyre error (block hash not found)"]
    G -- "Some(hash)" --> J["store.forkchoice_update()"]
    J -- "error" --> K["eyre error → init_l1 fails"]
    J -- "ok" --> L["Ok(())"]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: cmd/ethrex/initializers.rs
Line: 465-467

Comment:
**Missing env var now crashes `init_l1`**

The original function was intentionally gated on `if let Ok(...) = env::var("SYNC_BLOCK_NUM")` — if the variable is absent, it was a silent no-op. Replacing that with `env::var(...)?` propagates `VarError::NotPresent` as an error, so every node started without `SYNC_BLOCK_NUM` set will fail inside `init_l1`. The fix is to restore the optional behavior:

```rust
async fn set_sync_block(store: &Store) -> eyre::Result<()> {
    let Ok(block_number_str) = env::var("SYNC_BLOCK_NUM") else {
        return Ok(());
    };
    let block_number: u64 = block_number_str
        .parse()
        .map_err(|_| eyre::eyre!("SYNC_BLOCK_NUM environment variable is not a valid number"))?;
    // ... rest unchanged
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "refactor(l1): improve error handling in ..." | Re-trigger Greptile

Comment thread cmd/ethrex/initializers.rs Outdated
Comment thread cmd/ethrex/initializers.rs Outdated
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