{"record":{"id":"55bd76072b45fe03","repo":"linera-io/linera-protocol","slug":"expected-balance-expected-balance-actual-balan","errorCode":null,"errorMessage":"Expected balance: {expected_balance}, actual balance: {actual_balance}","messagePattern":"Expected balance: (.+?), actual balance: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"linera-service/src/benchmark.rs","lineNumber":246,"sourceCode":"        |((_, context, node_service), expected_balances)| {\n            try_join_all(apps.iter().zip(expected_balances).map(\n                |((_, sender_context, _), expected_balance)| async move {\n                    if expected_balance == Amount::ZERO {\n                        return Ok(()); // No transfers: The app won't be registered on this chain.\n                    }\n                    node_service.process_inbox(&context.default_chain).await?;\n                    let app = FungibleApp(node_service.make_application(\n                        &context.default_chain,\n                        &sender_context.application_id,\n                    )?);\n                    for i in 0.. {\n                        linera_base::time::timer::sleep(Duration::from_secs(i)).await;\n                        let actual_balance = app.get_amount(&context.owner).await;\n                        if actual_balance == expected_balance {\n                            break;\n                        }\n                        if i == 4 {\n                            bail!(\n                                \"Expected balance: {expected_balance}, actual balance: {actual_balance}\",\n                            );\n                        }\n                    }\n                    assert_eq!(app.get_amount(&context.owner).await, expected_balance);\n                    Ok(())\n                },\n            ))\n        },\n    ))\n    .await?;\n\n    Ok(())\n}\n\nstruct FungibleApp(ApplicationWrapper<FungibleTokenAbi>);\n\nimpl FungibleApp {","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-service/src/benchmark.rs#L228-L264","documentation":"After the benchmark fired all fungible-token transfers, it polls each receiving app's balance with sleeps of 0+1+2+3+4 seconds (~10s total). If the balance never reaches the expected value by the last iteration (i==4), it bails with expected vs actual. This means transfers (or the messages carrying them) did not fully process/converge within the wait window — some transfers failed outright (counted as Failures earlier) or cross-chain messages were still in flight.","triggerScenarios":"Running benchmark_with_fungible where a subset of transfer operations fail (shown in the 'Failures:' log line) or process_inbox/synchronization lag exceeds ~10 seconds under load; then the final assert would also fail. The bail fires first once i reaches 4 with a mismatching balance.","commonSituations":"Overloaded benchmark nodes (too many wallets/transactions for the machine) causing slow block processing; network latency between the client and validator set; some transfers rejected (insufficient balance for fees) so the expected balance can never be reached.","solutions":["Check the 'Successes:/Failures:' lines printed just before: if failures > 0, the mismatch is failed transfers, not slowness — fix why they failed (funding, fees, contention).","Reduce load (fewer wallets or transactions) so messages settle within the retry window.","Give the deployment more resources / closer validators to speed up message processing.","If you intentionally run heavy loads, raise the retry bound (i == 4) / sleep schedule in benchmark.rs before the final check."],"exampleFix":"// before\nfor i in 0.. {\n    linera_base::time::timer::sleep(Duration::from_secs(i)).await;\n    let actual_balance = app.get_amount(&context.owner).await;\n    if actual_balance == expected_balance { break; }\n    if i == 4 { bail!(\"Expected balance: {expected_balance}, actual balance: {actual_balance}\"); }\n}\n\n// after (heavy-load tuning): wider window and a diagnosed failure\nfor i in 0..10 {\n    linera_base::time::timer::sleep(Duration::from_secs(i)).await;\n    if app.get_amount(&context.owner).await == expected_balance { return Ok(()); }\n}\nbail!(\"balances did not converge in 45s; check the Failures count above for dropped transfers\");","handlingStrategy":"retry","validationCode":"// Before the balance check, confirm transfer success counts:\nanyhow::ensure!(failures == 0, \"{failures} transfers failed; balances cannot converge\");","typeGuard":null,"tryCatchPattern":"// The loop is the retry; on final mismatch, surface both balances plus the earlier\n// Successes/Failures counts so the operator can tell 'slow' from 'lost'.","preventionTips":["Tune load to what the deployment can settle within ~10s.","Fund wallets amply so no transfer fails on balance/fees.","Treat any non-zero Failures count as the real error; the balance bail is only the symptom."],"tags":["benchmark","fungible-token","eventual-consistency","load-testing","rust"],"backgroundTag":"state-convergence-timeout","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}