FuelLabs/fuel-core · error
The fee address index is out of bounds
Error message
The fee address index is out of bounds
What it means
The fee_address_index argument selects which entry of required_balances pays gas for the assembled transaction. AssembleTx::new rejects the request when fee_index (a u16) is >= required_balances.len(), i.e. the index points outside the list you provided.
Source
Thrown at crates/fuel-core/src/schema/tx/assemble_tx.rs:191
{
pub fn new(tx: Tx, mut arguments: AssembleArguments<'a>) -> anyhow::Result<Self> {
let max_inputs = arguments.consensus_parameters.tx_params().max_inputs();
let max_outputs = arguments.consensus_parameters.tx_params().max_outputs();
if tx.inputs().len() > max_inputs as usize {
return Err(anyhow::anyhow!(
"The transaction has more inputs than allowed by the consensus"
));
}
if tx.outputs().len() > max_outputs as usize {
return Err(anyhow::anyhow!(
"The transaction has more outputs than allowed by the consensus"
));
}
if arguments.fee_index as usize >= arguments.required_balances.len() {
return Err(anyhow::anyhow!("The fee address index is out of bounds"));
}
if has_duplicates(&arguments.required_balances, |balance| {
(balance.asset_id, balance.account.owner())
}) {
return Err(anyhow::anyhow!(
"required balances contain duplicate (asset, account) pair"
));
}
let base_asset_id = *arguments.consensus_parameters.base_asset_id();
let mut signature_witness_indexes = HashMap::<Address, u16>::new();
// Exclude inputs that already are used by the transaction
let mut has_predicates = false;
let inputs = tx.inputs();
let mut unique_used_asset = HashSet::new();
let mut set_contracts = HashSet::new();View on GitHub (pinned to b9d4d170da)
Solutions
- Set feeAddressIndex to the position of the account that should pay gas — usually 0 if the first required balance is the fee payer
- Ensure requiredBalances is non-empty and includes the fee-paying account
- Add a client-side assertion feeAddressIndex < requiredBalances.length before the mutation
Example fix
// before
await client.assembleTx(txBytes, { requiredBalances: balances, feeAddressIndex: 2 }); // balances.length === 1
// after
const feeAddressIndex = balances.findIndex((b) => b.account === FEE_PAYER);
if (feeAddressIndex < 0 || feeAddressIndex >= balances.length) throw new Error('bad feeAddressIndex');
await client.assembleTx(txBytes, { requiredBalances: balances, feeAddressIndex }); Defensive patterns
Strategy: validation
Validate before calling
function assertFeeIndex(requiredBalances: unknown[], feeAddressIndex: number) {
if (requiredBalances.length === 0) throw new Error('requiredBalances must not be empty');
if (!Number.isInteger(feeAddressIndex) || feeAddressIndex < 0 || feeAddressIndex >= requiredBalances.length) {
throw new Error(`feeAddressIndex ${feeAddressIndex} out of range for ${requiredBalances.length} balances`);
}
} Type guard
function isValidFeeIndex(balances: unknown[], i: unknown): i is number {
return typeof i === 'number' && i >= 0 && i < balances.length;
} Try / catch
catch (e) { if (/fee address index is out of bounds/.test(e.message)) { /* fix index to 0 or the fee payer's position and retry */ } else throw e; } Prevention
- Derive feeAddressIndex with findIndex on the balances array instead of hardcoding
- Default to feeAddressIndex = 0 when the first balance is the fee payer
- Add a unit test asserting the index invariant for every balances-building code path
When it happens
Trigger: Calling assembleTransaction with feeAddressIndex >= requiredBalances.length — e.g. passing requiredBalances: [] while leaving a nonzero feeAddressIndex, or reordering/shrinking the balances array after choosing the index.
Common situations: Empty requiredBalances array (fee-only assembly should still include one entry for the fee account); off-by-one when building balances dynamically; copying an index constant between code paths with different balance lists.
Related errors
- required balances contain duplicate (asset, account) pair
- fee index out of bounds
- The asset {} has multiple change policies
- The transaction has more outputs than allowed by the consens
- Unable to add more inputs because reached the maximum allowe
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/5a813b33c0b8846a.
Report an issue: GitHub.