{"record":{"id":"8868861b91e95d76","repo":"FuelLabs/fuels-rs","slug":"only-one-abigen-command-allowed","errorCode":null,"errorMessage":"Only one `Abigen` command allowed","messagePattern":"Only one `Abigen` command allowed","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"packages/fuels-macros/src/setup_program_test/parsing/validations.rs","lineNumber":23,"sourceCode":"use syn::{Error, LitStr, Result};\n\nuse crate::{\n    parse_utils::ErrorsExt,\n    setup_program_test::parsing::{\n        AbigenCommand, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,\n    },\n};\n\npub(crate) fn extract_the_abigen_command(\n    parent_span: Span,\n    abigen_commands: &[AbigenCommand],\n) -> Result<AbigenCommand> {\n    match abigen_commands {\n        [single_command] => Ok(single_command.clone()),\n        commands => {\n            let err = commands\n                .iter()\n                .map(|command| Error::new(command.span, \"Only one `Abigen` command allowed\"))\n                .combine_errors()\n                .unwrap_or_else(|| Error::new(parent_span, \"Add an `Abigen(..)` command!\"));\n\n            Err(err)\n        }\n    }\n}\n\npub(crate) fn validate_all_contracts_are_known(\n    abigen_command: &AbigenCommand,\n    deploy_commands: &[DeployContractCommand],\n) -> Result<()> {\n    extract_contracts_to_deploy(deploy_commands)\n        .difference(&names_of_program_bindings(\n            abigen_command,\n            ProgramType::Contract,\n        ))\n        .flat_map(|unknown_contract| {","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/FuelLabs/fuels-rs/blob/d9a250a51818dda64bfeb5ef7cc19cf27bdcd623/packages/fuels-macros/src/setup_program_test/parsing/validations.rs#L5-L41","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Merge the multiple Abigen blocks into one, putting all bindings inside that single command's lists.","Delete the duplicated block if it is a leftover.","Note the paired error message: if you instead have zero Abigen commands you will get 'Add an Abigen(..) command!'.","Recompile to confirm the single-command validation passes."],"exampleFix":"// before\nsetup_program_test!(\n    Abigen(contracts = [(name = \"a\", project = \"..\")]),\n    Abigen(contracts = [(name = \"b\", project = \"..\")]),\n)\n// after\nsetup_program_test!(\n    Abigen(contracts = [\n        (name = \"a\", project = \"..\"),\n        (name = \"b\", project = \"..\"),\n    ]),\n)","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep exactly one Abigen block per setup_program_test! and grow its lists instead of adding blocks.","After merge conflicts in macro invocations, cargo check immediately to catch duplicated blocks."],"tags":["rust","macro","compile-time","setup-program-test","abigen"],"backgroundTag":null,"analyzedSha":"d9a250a51818dda64bfeb5ef7cc19cf27bdcd623","analyzedAt":"2026-08-16T09:49:30.618Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}