{"record":{"id":"3c56c726dbbf9c95","repo":"unionlabs/union","slug":"no-balance-for-denom","errorCode":null,"errorMessage":"no balance for denom {}","messagePattern":"no balance for denom (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"tools/union-test/src/cosmos.rs","lineNumber":625,"sourceCode":"\n    pub async fn get_balance(\n        &self,\n        address: impl Into<String>,\n        denom: &str,\n    ) -> anyhow::Result<protos::cosmos::base::v1beta1::Coin> {\n        let req = QueryBalanceRequest {\n            address: address.into(),\n            denom: denom.to_string(),\n        };\n        let resp: QueryBalanceResponse = self\n            .rpc\n            .client()\n            .grpc_abci_query(\"/cosmos.bank.v1beta1.Query/Balance\", &req, None, false)\n            .await?\n            .into_result()?\n            .unwrap();\n        resp.balance\n            .ok_or_else(|| anyhow::anyhow!(\"no balance for denom {}\", denom))\n    }\n\n    pub async fn send_cosmwasm_transaction_with_retry(\n        &self,\n        contract: Addr,\n        msg: (Vec<u8>, Vec<Coin>),\n        signer: &LocalSigner,\n    ) -> Option<Result<TxResponse, BroadcastTxCommitError>> {\n        let max_retries = 5;\n        for attempt in 1..=max_retries {\n            let outcome = self\n                .send_cosmwasm_transaction(contract.clone(), msg.clone(), signer)\n                .await;\n\n            if let Some(Ok(_)) = &outcome {\n                return outcome;\n            }\n","sourceCodeStart":607,"sourceCodeEnd":643,"githubUrl":"https://github.com/unionlabs/union/blob/031785bb6dc6b957c624e62bc64c184409c97d7b/tools/union-test/src/cosmos.rs#L607-L643","documentation":"`CosmosClient::get_balance` issues a `/cosmos.bank.v1beta1.Query/Balance` grpc_abci_query and unwraps `resp.balance`. Cosmos SDK returns an empty balance when the account holds no Coin for that denom, and this code converts that None into an error rather than zero.","triggerScenarios":"Querying a denom the account has never held (zero balances are omitted by the bank module); a misspelled or differently-formatted denom (uatom vs atom, factory/ibc denom prefixes); the correct denom but an unfunded wallet.","commonSituations":"Test setup forgets to fund the account; faucet mint hasn't landed; base vs display denomination confusion on testnets; address copied for the wrong network.","solutions":["List the account's actual balances (`/cosmos.bank.v1beta1.Query/AllBalances`) and use the exact denom string returned","Fund the account (faucet or bank send) before the step that requires the balance","If zero is a legitimate state in your flow, branch on the Option instead of calling this helper"],"exampleFix":"// before\nlet coin = client.get_balance(&addr, \"uatom\").await?; \n// after\nlet amount = client\n    .get_balance(&addr, denom)\n    .await\n    .ok()\n    .flatten_amount_if_any() // Option<Coin>\n    .unwrap_or_else(|| Coin::default_for(denom));","handlingStrategy":"validation","validationCode":"// list real denoms before querying a specific one\nlet balances: QueryAllBalancesResponse = client\n    .rpc.client()\n    .grpc_abci_query(\"/cosmos.bank.v1beta1.Query/AllBalances\", &QueryAllBalancesRequest { address: addr.clone().into(), ..Default::default() }, None, false)\n    .await?.into_result()?.unwrap();\nanyhow::ensure!(balances.balances.iter().any(|c| c.denom == denom), \"denom {denom} not held by {addr}\");","typeGuard":null,"tryCatchPattern":"match client.get_balance(&addr, denom).await {\n    Ok(coin) => Ok(coin),\n    Err(e) if e.to_string().starts_with(\"no balance for denom\") => {\n        // decide explicitly: is zero acceptable, or should the account be funded first?\n        fund_if_needed(&addr, denom).await?;\n        client.get_balance(&addr, denom).await\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Fund accounts in test setup and assert on balances before the logic that consumes them","Use exact base denominations copied from AllBalances output, not display denominations"],"tags":["rust","cosmos-sdk","bank","balance","grpc"],"backgroundTag":null,"analyzedSha":"031785bb6dc6b957c624e62bc64c184409c97d7b","analyzedAt":"2026-08-16T06:24:09.996Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}