Difficulty in reliably mapping errors from Bitcoin Core due to unstable error codes and messages #33350

issue ziggie1984 openend this issue on September 9, 2025
  1. ziggie1984 commented at 1:25 pm on September 9, 2025: none

    Please describe the feature you’d like to see added.

    It’s becoming increasingly difficult to reliably map and handle errors originating from Bitcoin Core. The primary challenge stems from the frequent changes in both the error codes and the descriptive error text.

    Problem Description Our current error-handling logic relies on parsing the responses from Bitcoin Core. However, this approach is fragile for two main reasons:

    Unstable Error Codes: The numerical error codes returned by Bitcoin Core are not stable across versions. An error code that signifies a specific issue in one version might be changed or removed in a future update, which breaks any logic that depends on matching these codes.

    Changing Error Messages: Relying on string matching of the error messages is also unreliable. The text of these messages is frequently rephrased, updated, or otherwise modified between releases. This makes text-based error detection brittle and requires constant maintenance to keep up with the changes in Core.

    This instability creates a significant maintenance burden, as our error-handling code needs to be constantly revisited and updated to align with the latest changes in Bitcoin Core.

    A clear example of this ongoing struggle can be seen in this related issue/PR, which highlights the effort required to adapt to these changes: https://github.com/btcsuite/btcwallet/pull/1053

    Seeking a More Robust Solution Given these challenges, we are looking for better strategies to interpret errors from Bitcoin Core that are less susceptible to these frequent upstream changes.

    We are open to any tips or suggestions how to handle this. Are there more resilient patterns for error handling in this context that we should consider? Any advice would be greatly appreciated.

    No response

    Describe the solution you’d like

    No response

    Describe any alternatives you’ve considered

    No response

    Please leave any additional context

    No response

  2. ziggie1984 added the label Feature on Sep 9, 2025
  3. instagibbs commented at 1:58 pm on September 9, 2025: member
    Is there a easy to read table somewhere on how you are interpreting and using specific error codes / msgs and how your software is intended to respond to them? This seems like an twice a year issue, and as far as I know no one else is using the errors for non-debugging reasons, or they’re too shy to complain about the breaks.
  4. ziggie1984 commented at 2:15 pm on September 9, 2025: none

    We don’t have an easy table but I think for example this gives a good example:

    https://github.com/lightningnetwork/lnd/blob/master/sweep/fee_bumper.go#L568-L578

    In our fee bumper engine we only bump the fee of a transaction if the error is somehow related to an insufficient fee error, otherwise we drop this input from the sweeping system because problems like not having the correct signature or being already spent would cause us to never properly sweep this input.

    What I am more interested is, does core change these error strings or codes with the awareness that dependant code will have to update or is it not really a goal to stay backwards compatible in regards of the error codes/strings ?

    Yes I am really surprised that people are not using those error codes to decided based on that what is wrong with their transaction what they for example trying to broadcast. Especially testMempoolAccept is by the name actually built to test for a specific error to basically change the transaction accordingly.

    Maybe it would be good to always have a highlighting notification in the release notes when error codes/ errror strings change. With that we could react accordingly and update our software.

  5. instagibbs commented at 2:28 pm on September 9, 2025: member

    Speaking only for myself since I’m more familiar with both LN (by means of CLN) and Bitcoin Core sides…

    Yes I am really surprised that people are not using those error codes to decided based on that what is wrong with their transaction what they for example trying to broadcast.

    I think it’s honestly quite rare. People will craft transactions using information gleaned Core (like mempool minfee or fee estimator) and proactively avoid violating it. The software can’t do anything about other errors, other than report loudly in logs.

    Shower thought: Would a “this type of transaction will not work for some unfixable reason” vs “this may work later” vs “this may work with fees bumped” kind of status help? This is why I’m asking for more scenarios.

    Maybe it would be good to always have a highlighting notification in the release notes when error codes/ errror strings change. With that we could react accordingly and update our software.

    This definitely should have been done for TX_RECONSIDERABLE. New codes are pretty rare, this one being related to package relay internals.

    However strings will be changing, and transaction check ordering will change, especially going forward with the cluster mempool rewrite. e.g., ancestor limits are no more, no more rbf carveout, different RBF checks, dropped rules, etc. I don’t think it’s going to be possible to make promises otherwise.

  6. ziggie1984 commented at 3:33 pm on September 9, 2025: none

    Ok thank you for the information so far, feels like there is currently no easy way for us to proceed so we continue mapping the error strings. What would be very helpful is like a release-note highlight in case the error reporting for the RPC changes.

    Keeping this issue open for a bit in case somebody else has a better idea.

  7. instagibbs commented at 3:58 pm on September 9, 2025: member

    Chatting with some other devs, one other motivation for better/easier error codes would be to allow logging to be more sane.

    For instance, sendrawtransaction may throw an error if already in mempool, which if logged is incredibly noisy and useless for fire-and-forget wallets like CLN.

    submitpackage already behaves better in that respect, returning a success instead (as it is in the mempool).

  8. Roasbeef commented at 6:26 pm on September 9, 2025: none

    proactively avoid violating it

    Avoiding violating the rules is itself a moving target. Consider that a user can set config options in bitciond to: affect the min relay fee, reduce the mempool size, etc (min mempool fee is itself a dynamic value). Or the user picks a fee that’s below the min relay fee, and the transaction is rejected. Another example is if someone sends you some sats, and you go to spend that transaction zero conf, but get rejected as the ancestor chain is too long. Or if new policy rules are added that cause bitcoind to reject transaction that it previously accepted.

    If a consumer of the RPC API can consistently detect these cases, they can safely retry (or know it isn’t possible).

    RPC calls like submitpackage (or testmempoolaccept) help, but as there isn’t an atomic transaction submission API, something can show success with submitpacakge, but then rejected once it actually hits the mempool.

    Right now without set error codes, we’re forced to closely examine PRs for inadvertent breaks when error strings are “improved” (which typically don’t make the . Here’s one recent example: https://github.com/btcsuite/btcd/issues/2404:

    “non-mandatory-script-verify-flag” is replaced with “mempool-script-verify-flag-failed”

  9. instagibbs commented at 6:32 pm on September 9, 2025: member

    RPC calls like submitpackage (or testmempoolaccept) help, but as there isn’t an atomic transaction submission API, something can show success with submitpacakge, but then rejected once it actually hits the mempool.

    Sorry can you elaborate? submitpackage should return an error string if it doesn’t enter the local mempool

  10. Roasbeef commented at 5:32 pm on September 15, 2025: none

    Ah, I meant testmempoolaccept. testmempoolaccept was called, but a new/different error was returned, so we weren’t able to make a decisions w.r.t “should we retry or is it hosed”.

    Re atomic transaction submission, what I mean is that a sort of race condition can arise between the time you call testmempoolaccept, and when you actually submit the package.


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2025-09-19 18:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me