SwapChan
Never holds your keys · your wallet signs
blocktools CLI

Refusals and status codes

Every blocktools status and failure code, what causes it and what to do.

Every blocktools tool prints JSON lines. The last line carries status, and a refusal adds a failures list. This page covers every status and every failure code the tools can emit. For each one it gives the cause and what you should do. The code examples are run by scripts/e2e.d/refusals.sh (scripts/e2e-only/doc-run.py). That check also fails if a code the source can emit has no section here.

Measured on Linux only. The examples below run in the e2e gate on Linux. Exit codes on other platforms have not been measured.

The fixtures are built inside the runner from public test values, so you can run the commands yourself. $FX/btc.psbt is a one-input sweep of a made-up UTXO to $BTC_TO. The $FX/evm-*.hex files are unsigned EVM transactions built by hand by scripts/e2e-only/evm-fixture.py. $FX/key2 is the integer 2 used as a private key. None of these commands touches a real network.

Exit codes (measured)

exit meaning
0 ok / done / checksum_ok (success)
1 failed (verification found problems), refused (a signer or broadcaster would not act), aborted (no confirmation)
2 bad_input (the input could not be parsed, or a required flag is missing)

Statuses

ok

A result line for one item, for example one derived master key. You don't need to do anything.

done

The final line of a run that streams results, with count. A count of 0 means the tool found nothing. That is not an error.

echo "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" | seed-repair

checksum_ok

seed-repair: this candidate mnemonic passes the BIP-39 checksum. A passing checksum does not prove the phrase is yours. Derive addresses from it and match them against an address you know.

checksum_fail

In the vocabulary but not emitted by any current tool, so no example has been run. seed-repair reports only candidates that pass. A phrase with no passing candidate ends with done and count: 0.

no_candidates

seed-repair and the address planner: no candidate fits the input. Check the words or the address for typos. Allowing more changed words widens the search. Not run here.

too_many_candidates

The search space is larger than the cap. Narrow it down: fix the words you are sure of, give the known address, or reduce the number of edits allowed. Not run here.

bad_input

The input could not be parsed, or a required flag is missing. The error field says which one. Fix the input. Nothing was done.

echo zz | tx-verify

wrong_password

A wallet reader (dat-read, keystore-open, electrum-read, multibit-read, armory-read, blockchain-read, bitcoinj) decrypted with the given password and the integrity check failed. Try other candidates, for example with pw-candidates. Not run here, because the encrypted fixtures live in the crate tests.

unsupported

The file format, version, or script type is recognised but not handled. Nothing was extracted. Report the error field. Do not try to force it. Not run here.

error

An internal or I/O error, for example a network error in utxo-fetch or tx-broadcast. Nothing was signed or sent. Retry, or report it with the line shown.

failed

tx-verify found problems. See failures and the codes below.

refused

tx-sign or tx-broadcast would not act. See failures or error. Nothing was signed or sent.

tx-broadcast --chain btc --url http://127.0.0.1:9 < "$FX/btc.psbt"

aborted

The signer needs a typed confirmation on a TTY (/dev/tty) and did not get one. With no controlling terminal (the runner uses a new session) it always aborts. That is deliberate: scripts cannot sign without a human. Run it in a terminal and type the confirmation.

tx-sign --tx "$FX/evm-transfer.hex" --chain-id 1 --expect-to "$EVM_TO" --allow-warnings < "$FX/key2"

Failure codes (tx-verify, tx-sign)

has_warnings

The transaction has warnings (any warning except unsigned). Read each one in warnings. Pass --allow-warnings only once you understand every warning.

tx-verify --chain-id 1 --expect-to "$EVM_TO" < "$FX/evm-transfer.hex"

fee_over_10pct_of_inputs

The fee is more than 10% of what the inputs hold (UTXO chains), even though it is under the cap. This is usually a wrong change output or a unit slip. Rebuild the transaction. Pass an explicit --max-fee only if you meant to pay that share.

fee_above_cap

The fee is above the cap. fee_cap.source says where the cap came from (explicit, default_evm, chain_rate_x_vsize). Rebuild the transaction with a lower fee. Raise --max-fee only if you meant to pay that much.

tx-verify --max-fee 100 --expect-to "$BTC_TO" < "$FX/btc.psbt"

fee_unknown

The fee cannot be computed, because a raw Bitcoin transaction does not carry its input amounts. Verify the PSBT, which carries them, rather than the raw transaction.

tx-verify --chain btc --expect-to "$BTC_TO" < "$FX/btc-raw.hex"

chain_id_mismatch

The transaction's EVM chain id differs from --chain-id. Signing would make it valid on a different chain. Rebuild it for the chain you meant.

tx-verify --chain-id 8453 --allow-warnings --expect-to "$EVM_TO" < "$FX/evm-transfer.hex"

chain_id_not_pinned

An EVM transaction was verified without --chain-id. Pass the chain id you intend to use.

tx-verify --allow-warnings --expect-to "$EVM_TO" < "$FX/evm-transfer.hex"

no_chain_id

You pinned a chain id, but the transaction has none (a pre-EIP-155 legacy transaction). Rebuild it with a chain id.

no_replay_protection

The EVM transaction has no chain id, so anyone could replay it on every EVM chain. Rebuild it with a chain id. The signer refuses as well (refuse_no_chain_id).

tx-sign --tx "$FX/evm-legacy-no-chain-id.hex" --chain-id 1 --expect-to "$EVM_TO" < "$FX/key2"

token_call_not_transfer

The calldata calls a known token function that is not transfer (here, an unlimited approve). Approvals let someone else spend your tokens. Do not sign unless you set it up yourself.

tx-verify --chain-id 1 --expect-to "$EVM_TO" < "$FX/evm-approve.hex"

unknown_contract_call

The calldata is not a recognised call. blocktools cannot tell what it does. Do not sign it.

tx-verify --chain-id 1 --expect-to "$EVM_TO" < "$FX/evm-unknown-call.hex"

eth_value_with_token_call

A token transfer also sends ETH to the token contract. That ETH is almost certainly lost. Rebuild the transaction with value 0.

tx-verify --chain-id 1 --expect-to "$EVM_TO" < "$FX/evm-value-and-token.hex"

destination_not_expected

The EVM recipient (or the token recipient) is not one of the --expect-to addresses. Check the address character by character. Shown above together with token_call_not_transfer.

unexpected_output

A Bitcoin-family output goes to an address that is neither --expect-to nor --change. Do not sign. The address may have been swapped.

expected_destination_missing

None of the outputs pays an --expect-to address. Rebuild the transaction or correct the flag.

tx-sign --tx "$FX/btc.psbt" --expect-to bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 < "$FX/key2"

input_without_key

tx-sign was given a key that signs none of the inputs (the wrong key, or the wrong derivation path). Supply the key for the address the coins are on.

tx-sign --tx "$FX/btc.psbt" --expect-to "$BTC_TO" < "$FX/key2"

legacy_input_amount_unproven

A non-segwit input's amount is not proven by its previous transaction, so the fee could be a lie. Supply prev_tx. Not run here: tx-build already refuses such inputs earlier (legacy_input_needs_prev_tx, rc=2). Only an externally built PSBT reaches this check.

EVM contract tools (sig-hash, abi-decode, abi-encode, create-address)

These offline filters print {"status":"bad_input","error":CODE} and exit 2 on malformed input; they never guess. A selector, topic or error with no signature you supplied is not an error: {"status":"no_match"}, exit 0. Codes come from crates/evm; the strict decoder refuses any encoding Solidity would not produce.

Group Codes Human action
Hex bad_hex, odd_length_hex Pass 0x hex with an even number of digits
Signatures empty_signature, signature_needs_parens, unbalanced_parens, bad_signature_name, bad_signature_suffix, bad_type, bad_param, empty_param, bad_array_suffix, bad_array_length, tuple_needs_components, returns_needs_parens, signature_too_long, too_deep Fix the Solidity signature (for example uint7 or bytes33 do not exist)
ABI JSON bad_abi_json, abi_json_needs_array, bad_abi_item_type, bad_abi_item_name, bad_abi_params, abi_param_needs_type, abi_too_deep Pass a compiler ABI array, {abi:[…]}, or one signature per line
Strict decode data_too_short, data_shorter_than_selector, offset_out_of_bounds, offset_overflow, offset_or_length_out_of_bounds, offset_or_length_too_large, bytes_out_of_bounds, array_length_out_of_bounds, bytes_padding_missing, dirty_address, dirty_bool, dirty_uint, dirty_int, dirty_bytes_padding, string_not_utf8 The data does not match the signature, or is truncated or non-canonical: check the signature and that the whole field was copied
Logs bad_topic, topic_not_32_bytes, more_than_4_topics, topic_count_mismatch, no_matching_event, types_need_data_not_a_log Give the event declaration with the right indexed markers
Input JSON bad_input_json, input_json_has_no_input_data_or_topics, rpc_error_without_data, missing_input, missing_sig, output_needs_sig, output_needs_data, empty_input Pipe the JSON-RPC response or the hex field itself
Encode values bad_uint, uint_overflow, int_out_of_range, value_too_large_for_uint, number_not_integer_use_a_string, bad_bool, address_needs_0x, address_not_20_bytes, bad_eip55_checksum, expected_json_array, expected_scalar, too_many_values, missing_args Pass integers as decimal or 0x strings, addresses with a correct EIP-55 checksum (or all one case)
Addresses missing_deployer, create_needs_nonce_or_salt, bad_nonce, nonce_out_of_range_eip2681, bad_salt, salt_not_32_bytes, init_code_hash_not_32_bytes, create2_needs_exactly_one_of_init_code_hash_init_code Give --nonce (CREATE), or --salt with exactly one of --init-code-hash/--init-code (CREATE2)
Lookup lookup_needs_4_or_32_bytes, no_signature, cannot_read_file, cannot_read_abi_file Pass a selector or an event topic, and an existing signature file
echo 0xa9059cbb00 | abi-decode --sig 'transfer(address,uint256)'
abi-encode 'f(uint8)' 256
create-address --deployer 0x6ac7ea33f8831ea9dcc53393aaa88b25a785dbf0
echo '[' | abi-inspect
bytecode-inspect 0x1
echo '{}' | typed-data-verify --signer 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB
sol-tron-tx decode ff00ff
sol-tron-tx verify --expect '{"to":"TLa2f6VPqDgRE67v1736s7bJ8Ray5wYjU7"}' < "$FX/tron-transfer.hex"
printf '%064x\n' 1 | msg-sign --address 1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH --message 0xc0a96273d5c3fbe4d4000491f08daef9c17f88df846c1d6f57eb5f33c1fbd035
printf '%064x\n' 1 | msg-sign --address bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 --message hi
printf '%064x\n' 1 | msg-sign --address 19cAJn4Ms8jodBBGtroBNNpCZiHAWGAq7X --message hi
msg-verify --address bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 --message hi --sig AA==
printf '%064x' 1 | acct-tx keys --chain atom --hrp canto
acct-tx build --chain atom --from canto1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgfwgkv --pubkey 0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 --to canto1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqgfwgkv --amount 1 --fee 1 --gas 1 --sequence 0 --account-number 1