Skip to content

fix: improve miner thread robustness - #7510

Open
brice-stacks wants to merge 3 commits into
stacks-network:mainfrom
brice-stacks:feat/miner-retries
Open

fix: improve miner thread robustness#7510
brice-stacks wants to merge 3 commits into
stacks-network:mainfrom
brice-stacks:feat/miner-retries

Conversation

@brice-stacks

@brice-stacks brice-stacks commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Fixed the miner thread exiting (and stalling the chain for the remainder of the tenure) on transient error. The miner now retries when it hits DB contention, a parent block that has not been processed yet, a new parent block discovered mid-mining, or a mempool cache reset failure, instead of giving up on the tenure.

These changes are difficult to test and not worth the effort in my opinion.
Never mind -- this does need testing. I'm working on it.

Checklist

  • Test coverage for new or modified code paths
  • For new Clarity features or consensus changes, add property tests (see
    docs/property-testing.md)
  • Changelog fragment(s) or "no changelog" label added (see
    changelog.d/README.md). If this PR breaks
    anything for node operators or users, or requires them to manually do
    anything (such as adjust a setting), use the breaking category.
  • Required documentation changes (e.g.,
    rpc/openapi.yaml for RPC endpoints,
    event-dispatcher.md for new events)
  • New clarity functions have corresponding PR in clarity-benchmarking repo

Fixed the miner thread exiting (and stalling the chain for the remainder
of the tenure) on transient error. The miner now retries when it hits DB
contention, a parent block that has not been processed yet, a new parent
block discovered mid-mining, or a mempool cache reset failure, instead
of giving up on the tenure.

Copilot AI left a comment

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.

Pull request overview

Improves miner resilience by retrying recoverable failures instead of ending the tenure’s mining thread.

Changes:

  • Adds abort-aware retry handling for parent changes, DB errors, and timestamp validation.
  • Retries failed mempool cache resets.
  • Preserves underlying DB errors for retry classification.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
stacks-node/src/nakamoto_node/miner.rs Adds miner retry and abort behavior.
changelog.d/miner-thread-retry-transient-errors.fixed Documents the robustness fix.
Suppressed comments (1)

stacks-node/src/nakamoto_node/miner.rs:826

  • This arm classifies all DBError values as transient, but the wrapped error type also includes permanent conditions such as Corruption, ReadOnly, OldSchema, TooOldForEpoch, and BlockHeightOutOfRange (stackslib/src/util_lib/db.rs:54-91). Such faults will now loop and log until the tenure changes. Narrow this arm to explicitly retryable contention errors (and any intentionally retryable not-found cases), allowing all other errors to reach the fatal path.
            Err(
                ref e @ (NakamotoNodeError::MiningFailure(ChainstateError::DBError(_))
                | NakamotoNodeError::DBError(_)),

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread stacks-node/src/nakamoto_node/miner.rs
Comment thread stacks-node/src/nakamoto_node/miner.rs Outdated
Comment on lines +673 to +677
if let Err(e) = reset_result {
// A mempool DB error here is likely transient (e.g. lock
// contention); sleep and retry rather than exiting the miner
// thread.
warn!("Miner: failed to reset mempool caches, will try again: {e:?}");

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.

I don't think it hurts anything if the miner keeps retrying with no possibility of recovery, and that case might be more obvious in the logs. I'll take a closer look.

@cylewitruk-stacks cylewitruk-stacks Aug 12, 2026

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.

Only thing that I'd be careful of is the potential for this warn! to spam the logs 5x/second if it is e.g. some db/storage (or other persistent) issue 🙈 But the expect() above would maybe crash the thread then..

EDIT: But I guess we do that in a bunch of other places here already, so likely moot. I don't think it hurts anything, either -- the node will crash for other reasons if out of space or there's a corrupt db somewhere, etc.

@coveralls

coveralls commented Aug 12, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 31841396132

Warning

Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes.
Quick fix: rebase this PR. Learn more →

Coverage increased (+0.04%) to 86.625%

Details

  • Coverage increased (+0.04%) from the base build.
  • Patch coverage: 6 uncovered changes across 1 file (82 of 88 lines covered, 93.18%).
  • 90 coverage regressions across 25 files.

Uncovered Changes

File Changed Covered %
stacks-node/src/nakamoto_node/miner.rs 84 78 92.86%
Total (2 files) 88 82 93.18%

Coverage Regressions

90 previously-covered lines in 25 files lost coverage.

Top 10 Files by Coverage Loss Lines Losing Coverage Coverage
clarity/src/vm/functions/bitcoin_madhouse.rs 32 83.49%
stackslib/src/net/stackerdb/sync.rs 9 76.76%
stackslib/src/net/inv/epoch2x.rs 8 79.78%
stacks-common/src/deps_common/bitcoin/network/encodable.rs 4 88.71%
stacks-signer/src/client/stackerdb.rs 4 87.16%
stackslib/src/burnchains/burnchain.rs 3 72.03%
stackslib/src/net/neighbors/walk.rs 3 69.92%
stackslib/src/chainstate/burn/db/sortdb.rs 2 90.38%
stackslib/src/chainstate/nakamoto/coordinator/mod.rs 2 81.47%
stackslib/src/net/download/nakamoto/tenure.rs 2 89.02%

Coverage Stats

Coverage Status
Relevant Lines: 233056
Covered Lines: 201884
Line Coverage: 86.62%
Coverage Strength: 19313332.57 hits per line

💛 - Coveralls

Comment thread stacks-node/src/nakamoto_node/miner.rs Outdated
Replace a boolean flag that was set manually with an optional block id
to ensure that we reset the caches when appropriate.

@cylewitruk-stacks cylewitruk-stacks left a comment

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.

At a first glance this lgtm 👍 Not approving just yet only because I want to circle back with more focus and follow the error paths more closely.

/// mining attempt pops and returns one error until the list is empty.
pub static TEST_MINE_TRANSIENT_ERRORS: LazyLock<TestFlag<Vec<TestTransientError>>> =
LazyLock::new(TestFlag::default);

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.

Maybe we could squeeze something like this in somewhere?

Suggested change
// TODO: Move all of these test flags into a `cfg(test)`-gated `testing` module.

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment on lines +837 to +840
Err(
ref e @ (NakamotoNodeError::MiningFailure(ChainstateError::DBError(_))
| NakamotoNodeError::DBError(_)),
) => {
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.

4 participants