legacy wallets failing migration #35626

issue dooglus opened this issue on June 30, 2026
  1. dooglus commented at 4:44 PM on June 30, 2026: contributor

    Is there an existing issue for this?

    • I have searched the existing issues

    Current behaviour

    I have 3 old legacy wallets: w1, w2, and w3. I am attempting to migrate them to descriptor wallets using the migratewallet RPC in bitcoin v31.0

    For some reason, all 3 wallets contain a transaction that only 'belongs' to w3. None of the input or output addresses are 'ismine' for w1 or w2.

    When I attempt the migration, w3 works but w1 and w2 both fail like this:

    $ bitcoin-cli migratewallet w1
    error code: -4
    error message:
    Error: Transaction <txid> in wallet cannot be identified to belong to migrated wallets
    

    I don't know why the old wallets contain a transaction that they don't own, but I would still like to be able to migrate the wallets.

    I guess I can load the wallets into an old version of Core, use 'dumpwallet' to get all the private keys, and then import the corresponding descriptors into v31.0 - but that's not idea.

    Steps to reproduce

    I have no idea. The wallets are many years old now.

    How did you obtain Bitcoin Core

    Compiled from source

    What version of Bitcoin Core are you using?

    v31.0

    Operating system and version

    Debian 13

  2. fanquake added the label Wallet on Jun 30, 2026
  3. achow101 commented at 5:16 PM on June 30, 2026: member

    As a workaround, you can load it into an older version and do removeprunedfunds to delete the transaction and then migrate.

    I guess we should make this a warning instead of an error, wasn't expecting anyone to be able to hit this error.

  4. dooglus commented at 7:25 PM on June 30, 2026: contributor

    What I tried was to load them into an old version, then 'loadwallet', 'importprivkey', 'unloadwallet' to add the missing key into the 2 broken wallets.

    Weirdly one of them could then be migrated but the other still couldn't, with the same error message as before.

    Examining the wallets in the old version I found that the importprivkey had only added the missing key to one of the wallets. I'm not sure what I did wrong. Maybe 'unloadwallet' didn't flush everything properly, and I should have shut down the daemon before moving the wallets from the old datadir to the new one.

  5. hiSandog commented at 2:46 AM on July 1, 2026: none

    For legacy wallet migration failures, the most useful extra data is usually the wallet type/features and the migration log around the first failure. It would help to know whether the wallet uses private keys, watch-only entries, descriptors already partially present, or older Berkeley DB state. Also worth confirming that a backup was made before repeated migration attempts, since retries can make diagnosis harder.

  6. dooglus commented at 7:35 PM on July 1, 2026: contributor

    I was able to successfully migrate wallet w2 after adding a single missing private key to it.

    The wallet dump from running 'dumpwallet' contains 21670 change=1 private keys, 35340 label=* private keys (receiving addresses, I guess), 4996 reserve=1 private keys (the keypool?) and 62006 scripts (62006 = 21670 + 35340 + 4996, by the way, so I guess it contains the script for each private key)

    # Wallet dump created by Bitcoin Core v25.2
    # * Created on 2026-06-30T16:28:22Z
    # * Best block at time of backup was 0 (000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f),
    #   mined on 2009-01-03T18:15:05Z
    

    It doesn't contain watchonly entries or descriptors. I have always built with --with-incompatible-bdb for as long as I can remember. I'm using Berkeley DB v5.3.

    I made backups before all migrations, separate from Core's backups.

    I don't know how to find the wallet type/features or the migration log, unless you mean this from the debug.log:

    2026-06-30T15:50:38Z [w2] Last client version = 210100
    2026-06-30T15:50:45Z [w2] Legacy Wallet Keys: 62006 plaintext, 0 encrypted, 0 w/ metadata, 62006 total.
    2026-06-30T15:50:45Z [w2] Descriptors: 0, Descriptor Keys: 0 plaintext, 0 encrypted, 0 total.
    2026-06-30T15:50:45Z [w2] Wallet completed loading in            7503ms
    2026-06-30T15:50:45Z [w2] setKeyPool.size() = 0
    2026-06-30T15:50:45Z [w2] mapWallet.size() = 54723
    2026-06-30T15:50:45Z [w2] m_address_book.size() = 57011
    2026-06-30T15:50:45Z copied /.../.bitcoin/wallets/w2/wallet.dat to .../.bitcoin/wallets/w2_1782834645.legacy.bak
    2026-06-30T15:50:45Z [w2] Migrating wallet storage database from BerkeleyDB to SQLite.
    2026-06-30T15:51:01Z [w2] Setting spkMan to active: id = ..., type = legacy, internal = false
    2026-06-30T15:51:01Z [w2] Setting spkMan to active: id = ..., type = p2sh-segwit, internal = false
    2026-06-30T15:51:01Z [w2] Setting spkMan to active: id = ..., type = bech32, internal = false
    2026-06-30T15:51:01Z [w2] Setting spkMan to active: id = ..., type = bech32m, internal = false
    2026-06-30T15:51:01Z [w2] Setting spkMan to active: id = ..., type = legacy, internal = true
    2026-06-30T15:51:01Z [w2] Setting spkMan to active: id = ..., type = p2sh-segwit, internal = true
    2026-06-30T15:51:01Z [w2] Setting spkMan to active: id = ..., type = bech32, internal = true
    2026-06-30T15:51:02Z [w2] Setting spkMan to active: id = ..., type = bech32m, internal = true
    2026-06-30T15:51:02Z [w2] Releasing wallet w2..
    

    If there's something else I can provide, please let me know how.

  7. achow101 commented at 7:55 PM on July 1, 2026: member

    was it possible that you used the wallet in a development branch? The only thing I can think of is that there may have been prs which allow deleting scripts or unilaterally add transactions.

  8. dooglus commented at 11:15 AM on July 3, 2026: contributor

    I only ever built from the master branch, but not necessarily tagged releases.

    What's interesting is that whenever the migration tags a tx that the wallet has no private keys for, I can find the key in one of my other wallets and copy it over.

    I know the wallets are old enough that they were created before bitcoin had multi-wallet support, so I was having to shut down bitcoind and rename the wallets to switch between them. I'm wondering if doing that somehow caused cross-contamination.

    I still have a wallet that I have been unable to migrate. Each time I try, it stops at a txid that has no keys in the wallet. So I load the wallet up in an old version of bitcoin, import the missing private key, unload the wallet, copy it over to the new version of bitcoin and try again. Then it gives me a new txid with missing keys and I repeat the process. I've gone though about 50 iterations of this, but each time around the loop takes a little over a minute and I fear there may be thousands or tens of thousands of missing keys (or superfluous txs, however you see it).

  9. achow101 commented at 9:03 PM on July 3, 2026: member

    I know the wallets are old enough that they were created before bitcoin had multi-wallet support, so I was having to shut down bitcoind and rename the wallets to switch between them. I'm wondering if doing that somehow caused cross-contamination.

    AH, that could be the cause. BDB first writes data into database log files, before periodically writing that data into the wallet.dat file. We were also attempting to force that data to be written upon shutdown, but depending on the version you were running, I don't think this always happened. Regardless, if you were swapping only the wallet.dat file, there was the risk that the log file for the previous wallet was still present, and that the data from that log file could be written into the wallet.dat file that you swapped in, rather than or in addition to the wallet.dat the data was supposed to go into.

    You should be able to check how many superfluous transactions there are by comparing the mapWallet.size() = line in the debug.log to the number of unique txids that appear in listtransactions. Unfortunately, there isn't currently a way to list of all transactions stored in a wallet, listtransactions does IsMine checks before listing things out. But you can still pull up those transactions directly with gettransaction, and when you do that, I think it would have an empty details array. So maybe a faster alternative is to get all of the txids from your other wallets, see if they are present in the problem wallet with details: []. The transactions that appear like that can then either be removed from the problem wallet with removeprunedfunds, or you can import the relevant private keys.

  10. dooglus commented at 1:55 PM on July 5, 2026: contributor

    That sounds like the likely cause of the problem. I was assuming that if bitcoind had been shut down cleanly then I could swap the wallet.dat file out without problems.

    I used a script to do the swapping. It checks for the absence of a bitcoind process before doing the wallet.dat swap, but doesn't check for other database files.

    Thanks for the gettransaction / details hint. I was able to use that to get the w1 wallet into a state that I could then migrate it:

    bitcoin-cli-new -rpcwallet=w2 listtransactions '*' 99999 |
      jq -r .[].txid |
      sort -u |
      while read t; do bitcoin-cli-old -rpcwallet=w1 gettransaction $t 2>/dev/null |
        jq -r 'select(.details|length == 0)|.txid'
      done |
      while read t; do echo $t; bitcoin-cli-old -rpcwallet=w1 removeprunedfunds $t; done
    
Labels

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: 2026-07-07 05:51 UTC

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