{
 "number": 35760,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35760",
 "title": "wallet: make corrupted transaction records fail wallet loading instead of forcing a rescan",
 "author": "achow101",
 "author_association": "MEMBER",
 "created_at": "2026-07-20T22:11:07Z",
 "updated_at": "2026-09-16T20:16:37Z",
 "age_days": 58,
 "draft": false,
 "labels": [
  "Wallet"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "1e45c91abbb413cd60853a713e094e43945b3145",
 "head_ref": "wallet-rm-needs-rescan",
 "head_repo": "achow101/bitcoin",
 "head_history": [
  {
   "t": "2026-08-05T22:54:43Z",
   "sha": "fdd1a439fbf462c5d0fbfa2c4b7ac7f9c9a33a15"
  },
  {
   "t": "2026-08-19T20:36:57Z",
   "sha": "98045feee19c18e64927a594a3567d32fdca44e5"
  },
  {
   "t": "2026-08-21T20:29:17Z",
   "sha": "1e45c91abbb413cd60853a713e094e43945b3145"
  }
 ],
 "additions": 62,
 "deletions": 23,
 "changed_files": 8,
 "commit_count": 5,
 "size_bucket": "S",
 "mergeable_state": "clean",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "polespinasa",
      "url": "https://github.com/bitcoin/bitcoin/pull/35760#pullrequestreview-4969917474"
     },
     {
      "login": "jonatack",
      "url": "https://github.com/bitcoin/bitcoin/pull/35760#issuecomment-5345686759"
     },
     {
      "login": "rkrux",
      "url": "https://github.com/bitcoin/bitcoin/pull/35760#issuecomment-5425655052"
     }
    ],
    "approach_ack": [
     {
      "login": "pablomartin4btc",
      "url": "https://github.com/bitcoin/bitcoin/pull/35760#pullrequestreview-4879267838"
     },
     {
      "login": "jeanpablojp",
      "url": "https://github.com/bitcoin/bitcoin/pull/35760#pullrequestreview-5060820855"
     }
    ]
   },
   "conflicts": [
    {
     "number": 36167,
     "title": "[RFC] Enable `-Wunused`",
     "author": "fanquake"
    },
    {
     "number": 36133,
     "title": "wallet: store multipath descriptor",
     "author": "Sjors"
    },
    {
     "number": 33034,
     "title": "wallet: Store transactions in a separate sqlite table",
     "author": "achow101"
    },
    {
     "number": 27865,
     "title": "wallet: Track no-longer-spendable TXOs separately",
     "author": "achow101"
    }
   ]
  }
 },
 "acks_parsed": {
  "pablomartin4btc": {
   "kind": "approach_ack",
   "hash": null,
   "t": "2026-08-07T01:43:58Z",
   "stale": false
  },
  "jonatack": {
   "kind": "concept_ack",
   "hash": null,
   "t": "2026-08-19T17:27:19Z",
   "stale": false
  },
  "rkrux": {
   "kind": "concept_ack",
   "hash": "1e45c91",
   "t": "2026-08-26T12:59:03Z",
   "stale": false
  },
  "jeanpablojp": {
   "kind": "approach_ack",
   "hash": null,
   "t": "2026-08-30T12:30:45Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 2,
  "approach_ack": 2,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "jeanpablojp",
   "jonatack",
   "pablomartin4btc",
   "polespinasa",
   "rkrux"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "clean",
  "last_author_activity": "2026-08-26T17:15:28Z",
  "last_reviewer_activity": "2026-08-31T07:16:16Z",
  "last_reviewer": "polespinasa",
  "author_silent_days": 21,
  "waiting_on_author_days": 17,
  "days_since_update": 0
 },
 "refs": {
  "mentioned": [
   35501,
   35605,
   35944
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 35605,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-08-12",
    "title": "wallet: rpc: Deprecate `removeprunedfunds` RPC"
   },
   {
    "number": 35501,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-08-04",
    "title": "wallet: store all witness variants of a transaction"
   },
   {
    "number": 35944,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "doc, wallet: Add wallet corruption recovery guidance to managing-wallets.md"
   }
  ],
  "conflicts": [
   36167,
   36133,
   33034,
   27865
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/wallet/test/walletload_tests.cpp",
  "src/wallet/walletdb.cpp"
 ],
 "body": "In wallet loading, the `NEED_RESCAN` enum was only ever returned if the stored hash of a transaction did not match the calculated hash of the transaction. This would then trigger a rescan from genesis during loading, and then allow the wallet to be operational as if it were normal.\n\nHowever, it seems incorrect to be treating such corruption as acceptable. That transaction would be inserted to `mapWallet`, but not be added to `mapTxSpends` or any of the conflict tracking or to TXO caching. Furthermore, the rescan doesn't actually fix the problem, the incorrect record would persist, which means that the wallet would be rescanning the entire chain every time it is loaded. The only situation this could occur is if the wallet actually experienced corruption, so it's reasonable to return `CORRUPT` instead and force the user to load a backup or otherwise un-corrupt the wallet before it can be used.\n\nImplements the idea from https://github.com/bitcoin/bitcoin/pull/35501#discussion_r3617803101",
 "commits": [
  {
   "sha": "79eff69c162cf4433a8571c1b3af6b0a2d7f53bd",
   "date": "2026-08-21T20:27:21Z",
   "message": "walletdb: LoadToWallet failure is wallet corruption\n\nIf the wallet fails to load a transaction from the database, the wallet\nis corrupted."
  },
  {
   "sha": "1ba0884da54eb89569683a8d13ac130b3619c10a",
   "date": "2026-08-21T20:27:26Z",
   "message": "wallet: Remove DBErrors::NEED_RESCAN and rescan_required\n\nDBErrors::NEED_RESCAN is no longer returned by any part of wallet\nloading, so it can be deleted. AttachChain's rescan_required parameter\nwas only ever set to true when NEED_RESCAN was returned, so this can be\nremoved as well."
  },
  {
   "sha": "d261af4d9e0c0182ff7d4e1005ab6c2e5771f5a2",
   "date": "2026-08-21T20:28:38Z",
   "message": "wallet/test: add test for corrupt tx hash on wallet load\n\nVerifies that a tx record whose DB key does not match the hash of its\nserialised transaction causes `PopulateWalletFromDB` to return\n`DBErrors::CORRUPT`, pinning the behaviour introduced in this PR and\npreventing regressions."
  },
  {
   "sha": "c34db6bbef9dc85dacad9fa14d159ee95e5c7b82",
   "date": "2026-08-21T20:28:45Z",
   "message": "doc: add wallet corruption recovery guidance to managing-wallets.md\n\nAdds section 1.7 \"Recovering from a Corrupted Wallet\" to\ndoc/managing-wallets.md. The section documents that restoring from a\nknown-good backup is the only supported recovery path for corrupted\nwallet databases, and that there is no safe in-place repair mechanism.\n\nMotivated by achow101's conclusion in #35605: \"we should make the only\nsupported corruption recovery mechanism be to restore a backup and not\ndo any of this stuff with maybe being able to recover.\""
  },
  {
   "sha": "1e45c91abbb413cd60853a713e094e43945b3145",
   "date": "2026-08-21T20:28:45Z",
   "message": "doc: Release note for removing needs rescan"
  }
 ],
 "timeline": [
  {
   "t": "2026-08-05T22:54:43Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "fdd1a439fbf462c5d0fbfa2c4b7ac7f9c9a33a15"
  },
  {
   "t": "2026-08-07T01:43:58Z",
   "kind": "review",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "fdd1a439fbf462c5d0fbfa2c4b7ac7f9c9a33a15",
   "text": "Approach ACK at fdd1a439fbf462c5d0fbfa2c4b7ac7f9c9a33a15\n\nWhen a tx record's stored hash doesn't match the hash of its deserialized content, returning `NEED_RESCAN` was the wrong response: the rescan is not a reliable repair \u2014 it only overwrites the corrupted DB record as a side effect if the tx happens to be on-chain and wallet-relevant; if it isn't, the corrupted record stays in the DB permanently and the wallet rescans from genesis on every subsequent load. I think failing hard with `CORRUPT` makes no unverifiable assumptions about what the DB was supposed to contain, and signals unambiguous failure rather than attempting an unreliable recovery.\n\nHaving said that, the error message \"Error loading %s: Wallet corrupted\" gives the user no indication of what to do next.\n\nSince this is a user-visible behaviour change \u2014 wallet now fails to load instead of triggering a rescan \u2014 some release note seems required.\n\nAs a side effect, `bitcoin-wallet` info on a wallet with this corruption previously printed a misleading \"Rescanning wallet\" warning to stdout and silently exited with an error code \u2014 the tool never calls `AttachChain` so no rescan would ever run. It now correctly prints \"Wallet corrupted\" to stderr (but still no indication to the user of what to do next).\n\nOne suggestion: a unit test that writes a tx record with a mismatched key to the DB and asserts loading fails with `CORRUPT` would pin this behaviour and prevent regressions. I have one ready at 5e3212293b on top of this PR if useful."
  },
  {
   "t": "2026-08-10T14:34:41Z",
   "kind": "comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "text": "The PR correctly surfaces the corruption at load time rather than silently rescanning forever. The missing piece for users is what to do when they see that error \u2014 opened #35944 which adds a \"Recovering from a Corrupted Wallet\" section to `doc/managing-wallets.md` to address that gap.\n\nAlso worth noting: `walletdb.cpp:1050` has an error message that still says \"This can be fixed by removing transactions from wallet and rescanning.\" \u2014 that message covers a different corruption path but contradicts the same user-facing guidance. Could be addressed here since this PR is already touching the corruption detection code."
  },
  {
   "t": "2026-08-19T08:12:28Z",
   "kind": "comment",
   "who": "polespinasa",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThat's a small doc change probably worth adding here as an extra commit, as both PRs are small and related. I don't think there's the need for be looking for reviewers and going through the ACK process twice :)"
  },
  {
   "t": "2026-08-19T08:12:47Z",
   "kind": "review",
   "who": "polespinasa",
   "assoc": "MEMBER",
   "state": "COMMENTED",
   "commit": "fdd1a439fbf462c5d0fbfa2c4b7ac7f9c9a33a15",
   "text": "Aproach ACK\n\nHow can I test this?"
  },
  {
   "t": "2026-08-19T17:06:10Z",
   "kind": "comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nOpen a wallet file with sqlite, find a tx record and change the hash."
  },
  {
   "t": "2026-08-19T17:27:19Z",
   "kind": "comment",
   "who": "jonatack",
   "assoc": "MEMBER",
   "text": "Concept ACK. Worth a release note?"
  },
  {
   "t": "2026-08-19T17:33:19Z",
   "kind": "comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI've [suggested](https://github.com/bitcoin/bitcoin/pull/35760#pullrequestreview-4879267838) a unit test earlier that writes a tx record with a mismatched key to the DB and asserts loading fails with `CORRUPT` ->  https://github.com/bitcoin/bitcoin/commit/5e3212293b0e149b10ddad0a4a916fde1405b2ac."
  },
  {
   "t": "2026-08-19T17:38:32Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/wallet/walletdb.cpp",
   "commit": "304ec378b22d11607830702b2cee6303549d23d3",
   "in_reply_to": null,
   "text": "This error message is stale now and it should be updated to match the new behaviour."
  },
  {
   "t": "2026-08-19T20:36:57Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "98045feee19c18e64927a594a3567d32fdca44e5"
  },
  {
   "t": "2026-08-19T20:37:05Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/walletdb.cpp",
   "commit": "304ec378b22d11607830702b2cee6303549d23d3",
   "in_reply_to": 3815329837,
   "text": "Removed"
  },
  {
   "t": "2026-08-19T20:37:39Z",
   "kind": "comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nPulled the test\n\n[quoted text omitted]\nAdded a release note"
  },
  {
   "t": "2026-08-21T08:13:45Z",
   "kind": "comment",
   "who": "polespinasa",
   "assoc": "MEMBER",
   "text": "I just came with a concern regarding this change.\n\nBefore this PR a corrupted wallet would be anyway loaded after a rescan and would still show be able to spend funds, maybe not all due to corruption, but the valid and non-corrupted tx entries.\n\nIf we disable allowing this corrupted wallets, users that unconsciously did not create a backup will be unable to access any of their funds at all without switching to an old Core version."
  },
  {
   "t": "2026-08-21T08:46:56Z",
   "kind": "review_comment",
   "who": "polespinasa",
   "assoc": "MEMBER",
   "path": "src/wallet/walletdb.cpp",
   "commit": "1e45c91abbb413cd60853a713e094e43945b3145",
   "in_reply_to": null,
   "text": "in a79db308cb9bafc6c910e64f4cf6aceee7db55c3 walletdb: LoadToWallet failure is wallet corruption\n\nMaybe worth setting err?"
  },
  {
   "t": "2026-08-21T08:47:39Z",
   "kind": "review_comment",
   "who": "polespinasa",
   "assoc": "MEMBER",
   "path": "src/wallet/test/walletload_tests.cpp",
   "commit": "7bae5221ba69962531b1f9fc2e12a273a4df2c2d",
   "in_reply_to": null,
   "text": "in 7bae5221ba69962531b1f9fc2e12a273a4df2c2d wallet/test: add test for corrupt tx hash on wallet load\n\nrandom is included but never used"
  },
  {
   "t": "2026-08-21T09:18:55Z",
   "kind": "review_comment",
   "who": "polespinasa",
   "assoc": "MEMBER",
   "path": "src/wallet/test/walletload_tests.cpp",
   "commit": "1e45c91abbb413cd60853a713e094e43945b3145",
   "in_reply_to": null,
   "text": "in 7bae5221ba69962531b1f9fc2e12a273a4df2c2d wallet/test: add test for corrupt tx hash on wallet load\n\nThis test is wrong it is not testing the `DBErrors::CORRUPT` path intended to test. This can be easily tested by just running this test on master.\n\nThere are three path for `LoadTxRecords` that make the load fail as `DBErrors::CORRUPT`:\n```c++\n        try {\n            CWalletTx wtx{deserialize, value, ReadWtxVariants(batch, hash)};\n            if (wtx.GetHash() != hash) {\n                return DBErrors::CORRUPT;\n            }\n\n            if (wtx.nOrderPos == -1) {\n                any_unordered = true;\n            }\n\n            if (!pwallet->LoadToWallet(std::move(wtx))) {\n                err = \"Error: Corrupt transaction found\";\n                return DBErrors::CORRUPT;\n            }\n        } catch (const std::exception& e) {\n            err = strprintf(\"Error: Corrupt tx record found: %s\" ,e.what());\n            return DBErrors::CORRUPT;\n        }\n        return result;\n    });\n```\n\nThe one intended to test is the Corrupt transaction found catch is the first one which where a tx has an invalid hash.\nHowever this test is passing because the third one (the one inside the `catch`) is hit.\nThis happens because the transaction has no inputs and when trying to deserialize it runs out of bytes and throws with end of data.\n\n```bash\n$ ./build/bin/test_bitcoin --run_test=walletload_tests/wallet_load_corrupt_tx_hash -- -printtoconsole=1 -logthreadnames=1 -debug=walletdb 2>&1 | grep \"WalletLogPrintf\"\n2026-08-21T09:11:45.625958Z [test] [wallet/wallet.h:949] [WalletLogPrintf] [default wallet] Legacy Wallet Keys: 0 plaintext, 0 encrypted, 0 w/ metadata, 0 total.\n2026-08-21T09:11:45.625989Z [test] [wallet/wallet.h:949] [WalletLogPrintf] [default wallet] Descriptors: 0, Descriptor Keys: 0 plaintext, 0 encrypted, 0 total.\n2026-08-21T09:11:45.626255Z [test] [wallet/wallet.h:949] [WalletLogPrintf] [default wallet] Error: Corrupt tx record found: DataStream::read(): end of data: iostream error\n```\n\nThe fix is simple just add a dummy input to the transaction:\n\n```diff\n$ git diff\ndiff --git a/src/wallet/test/walletload_tests.cpp b/src/wallet/test/walletload_tests.cpp\nindex 6946503542..c5e07b64ee 100644\n--- a/src/wallet/test/walletload_tests.cpp\n+++ b/src/wallet/test/walletload_tests.cpp\n@@ -102,6 +102,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_load_corrupt_tx_hash, TestingSetup)\n     auto database = CreateMockableWalletDatabase();\n     {\n         CMutableTransaction mtx;\n+        mtx.vin.emplace_back();\n         mtx.vout.emplace_back(COIN, CScript() << OP_TRUE);\n         CWalletTx wtx{MakeTransactionRef(std::move(mtx)), TxStateInactive{}};\n         auto batch = database->MakeBatch();\n\n```\n\n```bash\n$ ./build/bin/test_bitcoin --run_test=walletload_tests/wallet_load_corrupt_tx_hash -- -printtoconsole=1 -logthreadnames=1 -debug=walletdb 2>&1 | grep \"WalletLogPrintf\"\n2026-08-21T09:14:29.109542Z [test] [wallet/wallet.h:949] [WalletLogPrintf] [default wallet] Legacy Wallet Keys: 0 plaintext, 0 encrypted, 0 w/ metadata, 0 total.\n2026-08-21T09:14:29.109585Z [test] [wallet/wallet.h:949] [WalletLogPrintf] [default wallet] Descriptors: 0, Descriptor Keys: 0 plaintext, 0 encrypted, 0 total.\n2026-08-21T09:14:29.109849Z [test] [wallet/wallet.h:949] [WalletLogPrintf] [default wallet]\n```\n\nAs said in https://github.com/bitcoin/bitcoin/pull/35760/changes/a79db308cb9bafc6c910e64f4cf6aceee7db55c3#r3828796073 the empty `WalletLogPrintf` is ugly, could be improved by adding an `err`."
  },
  {
   "t": "2026-08-21T19:27:25Z",
   "kind": "review_comment",
   "who": "pablomartin4btc",
   "assoc": "MEMBER",
   "path": "src/wallet/test/walletload_tests.cpp",
   "commit": "1e45c91abbb413cd60853a713e094e43945b3145",
   "in_reply_to": 3829019177,
   "text": "Thanks for catching this and working on a fix \u2014 checked that it works fine."
  },
  {
   "t": "2026-08-21T20:28:59Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/walletdb.cpp",
   "commit": "1e45c91abbb413cd60853a713e094e43945b3145",
   "in_reply_to": 3828796073,
   "text": "Doe"
  },
  {
   "t": "2026-08-21T20:29:05Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/test/walletload_tests.cpp",
   "commit": "7bae5221ba69962531b1f9fc2e12a273a4df2c2d",
   "in_reply_to": 3828800345,
   "text": "Removed"
  },
  {
   "t": "2026-08-21T20:29:12Z",
   "kind": "review_comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "path": "src/wallet/test/walletload_tests.cpp",
   "commit": "1e45c91abbb413cd60853a713e094e43945b3145",
   "in_reply_to": 3829019177,
   "text": "Fixed"
  },
  {
   "t": "2026-08-21T20:29:17Z",
   "kind": "force_push",
   "who": "achow101",
   "commit": "1e45c91abbb413cd60853a713e094e43945b3145"
  },
  {
   "t": "2026-08-21T20:31:10Z",
   "kind": "comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nThe user experience of such wallets is already pretty awful and I would expect there to be issues opened if anyone is actually running into this today."
  },
  {
   "t": "2026-08-22T07:01:34Z",
   "kind": "comment",
   "who": "polespinasa",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nYes I don't disagree with this, I am only pointing out that even if the experience is awful, might be the only way to recover funds o part of the funds.\n\nMaybe we could think in some way we can help the user instead of prohibiting access to the funds. If the transactions are the only thing corrupted we could give the user the option to list the descriptors so he can create a blank wallet and import them to recover funds. Or something like that, it's just an idea."
  },
  {
   "t": "2026-08-26T12:59:03Z",
   "kind": "comment",
   "who": "rkrux",
   "assoc": "MEMBER",
   "text": "Concept ACK 1e45c91\n\nI do prefer the wallet to stop and fail fast instead of trying to fix rare corrupted scenarios automatically _everytime on load_, which makes the wallet do too much and bloats the codebase as well. Ideally the corrupted scenarios of write time should fail-fast while writing itself (which I see might not be possible in every such case) instead of the read flow taking on the onus of fixing - unfortunate that the wallet has been doing this already and setting such a precedent.\n\nThere indeed is a slight concern regarding the user not being able to access the funds if the backup is not there, which is also not ideal though in the first place. But I don't think the wallet should preemptively try to fix automatically at load time as such corrupted scenarios should be very unlikely.\n\n[quoted text omitted]\nIs there even a way for the user to un-corrupt the wallet?"
  },
  {
   "t": "2026-08-26T17:15:28Z",
   "kind": "comment",
   "who": "achow101",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nDepends on their knowledge of the wallet. You can always use sqlite to manually modify records directly, outside of the wallet."
  },
  {
   "t": "2026-08-30T12:30:45Z",
   "kind": "review",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "state": "COMMENTED",
   "commit": "1e45c91abbb413cd60853a713e094e43945b3145",
   "text": "Approach ACK\n\nBuilt it, ran the unit tests and the wallet functional tests, and reproduced the corruption on regtest.\n\nThe description says the tx is inserted into `mapWallet` but not added to `mapTxSpends`. That stopped being true in #35501, where `LoadToWallet` started getting called on the mismatch path too. With the old code put back here, `IsSpent` on the prevout returns true. The rest of the argument, the record that stays behind and the rescan on every load, still holds."
  },
  {
   "t": "2026-08-30T12:30:45Z",
   "kind": "review_comment",
   "who": "jeanpablojp",
   "assoc": "CONTRIBUTOR",
   "path": "src/wallet/walletdb.cpp",
   "commit": "1e45c91abbb413cd60853a713e094e43945b3145",
   "in_reply_to": null,
   "text": "The two are swapped. In the description you call the DB key the stored hash and `wtx.GetHash()` the calculated one, and here the `strprintf` passes them the other way round. The new test writes under a zeroed key, so this is what it prints.\n\n```\nStored hash of 7c2ae489...40fe but an actual hash of 0000...0000\n```\n\nAnyone looking for that record in sqlite by the message searches for a key that isn't there."
  },
  {
   "t": "2026-08-31T07:16:16Z",
   "kind": "comment",
   "who": "polespinasa",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nI don't think that is an option lol.\n\n[quoted text omitted]\nI was not referring to fix corrupted scenarios on load, but to just let them load, with a big warning, if I am not wrong a corrupted wallet can still work, just the corrupted entries will not. That is a partial access to the funds which is, imho, better than 0 access. As I mentioned in https://github.com/bitcoin/bitcoin/pull/35760#issuecomment-5378840517, imagine if the wallet is corrupted, instead of throwing, just return a message saying `the wallet is corrupted, here are your private descriptors` (if wallet is unlocked) so the user can import them to some other place. I don't think that is too much complexity and it's not trying to fix the corrupt state. The user will fix it by importing descriptors to a new wallet."
  }
 ],
 "labels_log": [
  {
   "t": "2026-07-20T22:11:11Z",
   "action": "labeled",
   "label": "Wallet",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-04T22:54:43Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  },
  {
   "t": "2026-08-06T00:47:50Z",
   "action": "unlabeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 13108,
 "text_tokens_estimate": 3277,
 "changed_paths": [
  "doc/managing-wallets.md",
  "doc/release-notes-35760.md",
  "src/wallet/test/walletload_tests.cpp",
  "src/wallet/wallet.cpp",
  "src/wallet/wallet.h",
  "src/wallet/walletdb.cpp",
  "src/wallet/walletdb.h",
  "src/wallet/wallettool.cpp"
 ],
 "files": [
  {
   "path": "doc/managing-wallets.md",
   "add": 19,
   "del": 0
  },
  {
   "path": "doc/release-notes-35760.md",
   "add": 6,
   "del": 0
  },
  {
   "path": "src/wallet/test/walletload_tests.cpp",
   "add": 23,
   "del": 0
  },
  {
   "path": "src/wallet/wallet.cpp",
   "add": 9,
   "del": 18
  },
  {
   "path": "src/wallet/wallet.h",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/wallet/walletdb.cpp",
   "add": 3,
   "del": 2
  },
  {
   "path": "src/wallet/walletdb.h",
   "add": 0,
   "del": 1
  },
  {
   "path": "src/wallet/wallettool.cpp",
   "add": 1,
   "del": 1
  }
 ],
 "test_lines": 23,
 "git": {
  "head": "1e45c91abbb413cd60853a713e094e43945b3145",
  "head_matches_backup": true,
  "base": "c4fbd3c72114e3466329ec6f4b0f0a4b7ebce3b1",
  "commits": [
   {
    "sha": "79eff69c16",
    "subject": "walletdb: LoadToWallet failure is wallet corruption",
    "files": 1,
    "add": 3,
    "del": 2
   },
   {
    "sha": "1ba0884da5",
    "subject": "wallet: Remove DBErrors::NEED_RESCAN and rescan_required",
    "files": 4,
    "add": 11,
    "del": 21
   },
   {
    "sha": "d261af4d9e",
    "subject": "wallet/test: add test for corrupt tx hash on wallet load",
    "files": 1,
    "add": 23,
    "del": 0
   },
   {
    "sha": "c34db6bbef",
    "subject": "doc: add wallet corruption recovery guidance to managing-wallets.md",
    "files": 1,
    "add": 19,
    "del": 0
   },
   {
    "sha": "1e45c91abb",
    "subject": "doc: Release note for removing needs rescan",
    "files": 1,
    "add": 6,
    "del": 0
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "b6c00b1b22d974ce",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}