{"record":{"id":"bcb54c52c7d23ead","repo":"linera-io/linera-protocol","slug":"incorrecttransferamount","errorCode":"IncorrectTransferAmount","errorMessage":"ExecutionError::IncorrectTransferAmount","messagePattern":"ExecutionError::IncorrectTransferAmount","errorType":"exception","errorClass":"ExecutionError","httpStatus":null,"severity":"error","filePath":"linera-execution/src/system.rs","lineNumber":751,"sourceCode":"        source: AccountOwner,\n        recipient: Account,\n        amount: Amount,\n    ) -> Result<Option<OutgoingMessage>, ExecutionError> {\n        if source == AccountOwner::CHAIN {\n            let authenticated_owner =\n                authenticated_owner.ok_or(ExecutionError::UnauthenticatedTransferOwner)?;\n            ensure!(\n                self.ownership.get().await?.is_owner(&authenticated_owner),\n                ExecutionError::UnauthenticatedTransferOwner\n            );\n        } else {\n            ensure!(\n                authenticated_owner == Some(source)\n                    || authenticated_application_id.map(AccountOwner::from) == Some(source),\n                ExecutionError::UnauthenticatedTransferOwner\n            );\n        }\n        ensure!(\n            amount > Amount::ZERO,\n            ExecutionError::IncorrectTransferAmount\n        );\n        self.debit(&source, amount).await?;\n        self.credit_or_send_message(source, recipient, amount).await\n    }\n\n    /// Claims `amount` from `source`'s account on `target_id` and transfers it to `recipient`.\n    pub async fn claim(\n        &mut self,\n        authenticated_owner: Option<AccountOwner>,\n        authenticated_application_id: Option<ApplicationId>,\n        source: AccountOwner,\n        target_id: ChainId,\n        recipient: Account,\n        amount: Amount,\n    ) -> Result<Option<OutgoingMessage>, ExecutionError> {\n        ensure!(","sourceCodeStart":733,"sourceCodeEnd":769,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-execution/src/system.rs#L733-L769","documentation":"Native-token transfers must carry a strictly positive amount; this error is raised when amount is Amount::ZERO. It fires after owner authentication succeeds but before self.debit runs, so no balance changes and the transaction is rejected cleanly.","triggerScenarios":"Submitting SystemOperation::Transfer with amount zero; an application calling runtime.transfer(source, destination, Amount::ZERO); amounts computed from user input, rounding, or unit conversion that underflowed to zero (e.g. integer division applied before multiplication when converting display units to the 10^-9 base unit).","commonSituations":"Parsing an empty or '0' amount string from CLI or GraphQL input; off-by-one or integer-division bugs producing 0; test or health-check transactions sent with a zero amount; unit-conversion mistakes between human-readable LLN units and the smallest supported unit.","solutions":["Validate amount > Amount::ZERO before building or submitting the transfer operation.","Trace where the amount was computed and look for integer division or premature rounding that can collapse it to zero.","When converting user-entered amounts, compute in the smallest unit with checked arithmetic (try_mul/try_add) and reject non-positive results at the boundary."],"exampleFix":"// before: amount parsed from user input can be zero\nlet amount = Amount::from_str(&input)?;\nruntime.transfer(source, recipient, amount);\n\n// after: reject non-positive amounts before touching the system API\nlet amount = Amount::from_str(&input)?;\nensure!(!amount.is_zero(), \"transfer amount must be positive\");\nruntime.transfer(source, recipient, amount);","handlingStrategy":"validation","validationCode":"ensure!(\n    !amount.is_zero(),\n    \"transfer amount must be positive\"\n);\nlet _ = source; // then submit the Transfer operation","typeGuard":"fn is_incorrect_transfer_amount(e: &ExecutionError) -> bool {\n    matches!(e, ExecutionError::IncorrectTransferAmount)\n}","tryCatchPattern":"match result {\n    Err(ExecutionError::IncorrectTransferAmount) => {\n        // Amount was zero: fix the amount computation/input, then resubmit.\n    }\n    Err(e) => return Err(e.into()),\n    Ok(value) => { /* ... */ }\n}","preventionTips":["Reject zero amounts at the input boundary (CLI, GraphQL, app operations) before they reach the system API.","Compute amounts with checked arithmetic and do unit conversions in the smallest unit to avoid underflow to zero.","Add unit tests for the zero and minimum-one-nanolln cases in transfer paths."],"tags":["linera","transfer","amount","validation"],"backgroundTag":"zero-amount-transfer","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}