linera-io/linera-protocol · error · ExecutionError
IncorrectTransferAmount
IncorrectTransferAmount
Error message
ExecutionError::IncorrectTransferAmount
What it means
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.
Source
Thrown at linera-execution/src/system.rs:751
source: AccountOwner,
recipient: Account,
amount: Amount,
) -> Result<Option<OutgoingMessage>, ExecutionError> {
if source == AccountOwner::CHAIN {
let authenticated_owner =
authenticated_owner.ok_or(ExecutionError::UnauthenticatedTransferOwner)?;
ensure!(
self.ownership.get().await?.is_owner(&authenticated_owner),
ExecutionError::UnauthenticatedTransferOwner
);
} else {
ensure!(
authenticated_owner == Some(source)
|| authenticated_application_id.map(AccountOwner::from) == Some(source),
ExecutionError::UnauthenticatedTransferOwner
);
}
ensure!(
amount > Amount::ZERO,
ExecutionError::IncorrectTransferAmount
);
self.debit(&source, amount).await?;
self.credit_or_send_message(source, recipient, amount).await
}
/// Claims `amount` from `source`'s account on `target_id` and transfers it to `recipient`.
pub async fn claim(
&mut self,
authenticated_owner: Option<AccountOwner>,
authenticated_application_id: Option<ApplicationId>,
source: AccountOwner,
target_id: ChainId,
recipient: Account,
amount: Amount,
) -> Result<Option<OutgoingMessage>, ExecutionError> {
ensure!(View on GitHub (pinned to 6c226ddcb3)
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.
Example fix
// before: amount parsed from user input can be zero let amount = Amount::from_str(&input)?; runtime.transfer(source, recipient, amount); // after: reject non-positive amounts before touching the system API let amount = Amount::from_str(&input)?; ensure!(!amount.is_zero(), "transfer amount must be positive"); runtime.transfer(source, recipient, amount);
Defensive patterns
Strategy: validation
Validate before calling
ensure!(
!amount.is_zero(),
"transfer amount must be positive"
);
let _ = source; // then submit the Transfer operation Type guard
fn is_incorrect_transfer_amount(e: &ExecutionError) -> bool {
matches!(e, ExecutionError::IncorrectTransferAmount)
} Try / catch
match result {
Err(ExecutionError::IncorrectTransferAmount) => {
// Amount was zero: fix the amount computation/input, then resubmit.
}
Err(e) => return Err(e.into()),
Ok(value) => { /* ... */ }
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- IncorrectClaimAmount
- MetaMask is not connected with the requested owner: ${owner}
- Incoming message bundle in block proposed to {chain_id} has
- Checkpoint precondition failed: Checkpoint must be the first
- InvalidCrossChainRequest
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/bcb54c52c7d23ead.
Report an issue: GitHub.