FuelLabs/fuels-rs · error · syn::Error

Only one `Abigen` command allowed

Error message

Only one `Abigen` command allowed

What it means

Compile-time validation error from setup_program_test: extract_the_abigen_command matched the collected Abigen(...) commands against the [single_command] pattern and got two or more. The macro permits exactly one Abigen command per invocation, and an error is attached to each offending command's span.

Source

Thrown at packages/fuels-macros/src/setup_program_test/parsing/validations.rs:23

use syn::{Error, LitStr, Result};

use crate::{
    parse_utils::ErrorsExt,
    setup_program_test::parsing::{
        AbigenCommand, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,
    },
};

pub(crate) fn extract_the_abigen_command(
    parent_span: Span,
    abigen_commands: &[AbigenCommand],
) -> Result<AbigenCommand> {
    match abigen_commands {
        [single_command] => Ok(single_command.clone()),
        commands => {
            let err = commands
                .iter()
                .map(|command| Error::new(command.span, "Only one `Abigen` command allowed"))
                .combine_errors()
                .unwrap_or_else(|| Error::new(parent_span, "Add an `Abigen(..)` command!"));

            Err(err)
        }
    }
}

pub(crate) fn validate_all_contracts_are_known(
    abigen_command: &AbigenCommand,
    deploy_commands: &[DeployContractCommand],
) -> Result<()> {
    extract_contracts_to_deploy(deploy_commands)
        .difference(&names_of_program_bindings(
            abigen_command,
            ProgramType::Contract,
        ))
        .flat_map(|unknown_contract| {

View on GitHub (pinned to d9a250a518)

Solutions

  1. Merge the multiple Abigen blocks into one, putting all bindings inside that single command's lists.
  2. Delete the duplicated block if it is a leftover.
  3. Note the paired error message: if you instead have zero Abigen commands you will get 'Add an Abigen(..) command!'.
  4. Recompile to confirm the single-command validation passes.

Example fix

// before
setup_program_test!(
    Abigen(contracts = [(name = "a", project = "..")]),
    Abigen(contracts = [(name = "b", project = "..")]),
)
// after
setup_program_test!(
    Abigen(contracts = [
        (name = "a", project = ".."),
        (name = "b", project = ".."),
    ]),
)
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Writing two Abigen(...) blocks in one setup_program_test! invocation, e.g. one for contracts and another for scripts, or duplicating a block while reorganizing the test.

Common situations: Splitting bindings by program type into multiple Abigen blocks (the correct form is a single Abigen with contracts=[...], scripts=[...] sections); merge-conflict artifacts leaving both copies of a block; copying a working block to extend it instead of editing in place.

Related errors


AI-assisted analysis of FuelLabs/fuels-rs@d9a250a518 (2026-08-16). Data as JSON: /api/errors/8868861b91e95d76. Report an issue: GitHub.