Post
Share your knowledge.
+15
Sui Move Error - Unable to process transaction No valid gas coins found for the transaction
When I do this:
// Split payment from primary coin
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
// Use the original coin for gas payment
tx.setGasPayment([{
objectId: primaryCoin.coinObjectId,
version: primaryCoin.version,
digest: primaryCoin.digest
}]);
tx.setGasBudget(10_000_000);
It complains about mutatable objects cannot appear more than one in one transaction. When I remove the gas payment, it complains "Unable to process transaction No valid gas coins found for the transaction.". My contract function accepts .01 sui in exchange for an NFT
- Sui
- Transaction Processing
- Move
Answers
19You are running into a core Sui Move and Sui transaction model restriction: the same coin object cannot be used both as a gas coin and as an input to another command in the same transaction. This is enforced to prevent double-spending and ensure transaction safety.
Why this happens
- When you use
primaryCoin
insplitCoins
, it becomes a mutable input to the transaction. - When you also set it as the gas coin (
setGasPayment
), you are trying to use the same object in two roles. - Sui does not allow a mutable object (like a coin being split) to also be used as the gas coin in the same transaction.
This is confirmed by the error in your context:
mutatable objects cannot appear more than one in one transaction
And in the Sui Move test context:
Invalid taking of the Gas coin. It can only be used by-value with TransferObjects
(see source)
What you need to do
You must use a different coin for gas than the one you are splitting or otherwise mutating in the transaction.
Solution
- Ensure you have at least two SUI coins in your wallet.
- Use one coin for splitting/payment, and another for gas.
Example Flow
Suppose you have two coins: primaryCoin
and gasCoin
.
// Split payment from primary coin (not used for gas)
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
// Set a different coin for gas payment
tx.setGasPayment([{
objectId: gasCoin.coinObjectId,
version: gasCoin.version,
digest: gasCoin.digest
}]);
tx.setGasBudget(10_000_000);
primaryCoin
is used for splitting and payment.gasCoin
is used only for gas.
If you only have one coin, you must first split it in a separate transaction, so you have two coins for the next transaction.
References
This is a fundamental design choice in Sui to ensure transaction safety and prevent double-spending. It can be confusing at first, but once you get used to always keeping at least two coins in your wallet (one for gas, one for other operations), it becomes second nature. If you ever run into this error, just remember: never use the same coin for both gas and as a mutable input in the same transaction
Always select a distinct coin object for gas payment, separate from any coin you intend to mutate or transfer. If you only have one coin, split it in a prior transaction to create a second coin object for subsequent operations.
You are running into a common Sui Move transaction design constraint the same coin object cannot be used both as a mutable input (e.g., for splitting or transferring) and as the gas coin in a single transaction.
Why this happens
- When you use tx.splitCoins(tx.object(primaryCoin.coinObjectId), ...), you are marking primaryCoin as a mutable input.
- When you also set it as the gas coin with tx.setGasPayment(...), Sui sees the same object being used in two roles, which is not allowed.
- If you remove the gas payment, Sui cannot find a valid gas coin, hence the "No valid gas coins found for the transaction" error.
From context:
Transaction Effects Status: Invalid usage of value. Mutably borrowed values require unique usage. Immutably borrowed values cannot be taken or borrowed mutably. Taken values cannot be used again. (source)
How to fix
You must use a different coin for gas than the one you are splitting or transferring.
The Solution: Have at least two SUI coins in your wallet. Use one for the payment (splitting/transferring), and a different one for gas.
Example Flow
- Select two coins:
- primaryCoin (for payment)
- gasCoin (for gas)
- Split and pay with primaryCoin:
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
- Set gas payment with gasCoin:
tx.setGasPayment([{
objectId: gasCoin.coinObjectId,
version: gasCoin.version,
digest: gasCoin.digest
}]);
tx.setGasBudget(10_000_000);
Do not use the same coin object for both payment and gas.
My Reference
Sui Move: Invalid taking of the Gas coin. It can only be used by-value with TransferObjects
The error occurs because you're trying to use the original primaryCoin
object (which is consumed during the splitCoins
operation) as gas payment. After splitting, the original coin's version/digest becomes invalid, causing the "mutatable objects cannot appear more than one" error when referenced again.
To fix do not manually set gas payment using the pre-split primaryCoin
object. And nsure your primaryCoin
has sufficient balance to cover both:
- The payment amount (
requiredPaymentAmount
= 0.01 SUI) - The gas budget (
10_000_000
= 0.01 SUI) → Total needed: ≥ 0.02 SUI
Just try
// Split payment from primary coin (leaves remaining balance in primaryCoin)
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
// DO NOT setGasPayment manually - SDK auto-uses updated primaryCoin for gas
tx.setGasBudget(10_000_000); // Gas paid from primaryCoin's remaining balance
Bravo!!!
To fix the problem you're running into with the Sui transaction error about no valid gas coins found or mutable objects showing up more than once, it's because you can't use the same coin for both splitting off the payment and covering gas fees, as gas coins need to stay separate from the items you're tweaking in the deal. The easy tweak is to split the payment straight from the gas source instead of your main coin, so change it to something like
const paymentCoin = tx.splitCoins(tx.gas(), [tx.pure.u64(requiredPaymentAmount)]);
then drop the manual gas payment line altogether since the system will pick it up on its own, and keep your gas budget set as usual. This lets you pull from the gas coin without clashing, as long as your wallet has plenty to handle the 0.01 Sui payment plus fees.
This happens because you're trying to use the same coin object (primaryCoin
) both as gas payment and as input to splitCoins
, which makes it a mutable reference used in two different contexts — and Sui doesn't allow that for safety and linear logic (since coins are linear objects).
The way IMHO is to not manually set gas payment at all. Just let the Sui wallet/client automatically select an appropriate gas coin. Only use setGasPayment
if you really need to specify which coin pays for gas (e.g., multi-coin wallets, specific gas management). Otherwise, avoid it.
Try the following:
// Split the primary coin to get a payment coin
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
// Do your call that sends .01 SUI and gets an NFT
tx.moveCall({
target: `${packageId}::your_module::buy_nft`,
arguments: [
paymentCoin,
// other args...
],
});
// DO NOT set gas payment manually
// tx.setGasPayment(...) ← Remove this line
// Optional: set budget
tx.setGasBudget(10_000_000);
// Send the transaction
const result = await signer.signAndExecuteTransactionBlock({
transactionBlock: tx,
options: { showEffects: true },
});
Sui will:
- Automatically choose a gas coin (could be the same one or another SUI coin in the wallet).
- Handle the
splitCoins
safely. - Use a different coin (or sometimes the same one, but handled safely under the hood via proper object versioning).
Important: As long as your wallet has at least 1 $SUI that can cover gas, this will work.
This issue happens because you’re using the same coin (primaryCoin) for both gas and as an input in splitCoins, which isn’t allowed in Sui due to its rules around linear objects and safe mutation.
To fix it, don’t manually set the gas payment. Let the Sui wallet or client auto-select a suitable gas coin. You only need setGasPayment in advanced cases (like precise coin control). Here’s the clean approach:
// Split the primary coin to create a new payment coin
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
// Call your function using the new coin
tx.moveCall({
target: ${packageId}::your_module::buy_nft,
arguments: [paymentCoin],
});
// No manual gas setting — remove tx.setGasPayment(...)
// Set your gas budget
tx.setGasBudget(10_000_000);
// Execute the transaction
const result = await signer.signAndExecuteTransactionBlock({
transactionBlock: tx,
options: { showEffects: true },
});
Sui will safely pick a gas coin from your wallet (as long as one is available) and handle everything behind the scenes
This error happens because you’re trying to use the same coin both as the gas object and for a split operation, which breaks Sui’s rule against having two mutable references to the same object in one transaction. Splitting primaryCoin modifies it while also producing a new coin, and both can’t coexist in the same transaction. To fix this, you should:
* Use separate coins: one dedicated for gas, another for splitting or payments.
* Or, merge enough balance from another coin into primaryCoin before the transaction so it can cover all costs without duplication.
In short: always ensure that the coin used for gas is different from the one being split or passed into contract calls to prevent conflicts.
Issues
You're encountering two main issues:
-
Mutability Error: Attempting to use the same coin object for both gas payment and transaction input leads to the error: "Mutable objects cannot appear more than once in one transaction."
-
Missing Gas Coin: Without a valid gas coin, the error "Unable to process transaction: No valid gas coins found for the transaction" occurs.
Solution
To resolve these issues:
-
Split the Primary Coin for Payment: Use
tx.splitCoins
to create a new coin for the NFT purchase, ensuring it's separate from the gas payment. -
Set a Separate Gas Coin: Assign a different coin for gas payment using
tx.setGasPayment
. -
Define Gas Budget: Set an appropriate gas budget using
tx.setGasBudget
.
Code
// Step 1: Split the primary coin for payment
const [paymentCoin] = tx.splitCoins(
tx.object(primaryCoin.coinObjectId),
[tx.pure.u64(requiredPaymentAmount)]
);
// Step 2: Set a separate gas payment coin
const gasCoin = tx.object(gasCoinObjectId);
tx.setGasPayment([{
objectId: gasCoin.coinObjectId,
version: gasCoin.version,
digest: gasCoin.digest
}]);
// Step 3: Set the gas budget for the transaction
tx.setGasBudget(10_000_000);
The error occurs because you're attempting to split and use the same coin for both payment and gas, violating Sui's rule against mutable object duplication in a transaction. When you split primaryCoin
, it creates a new coin while mutating the original—both cannot appear in the same transaction. To resolve this, use two separate coins: one for gas payment and another for the split payment operation. Alternatively, merge sufficient gas from another coin into primaryCoin
before the transaction to cover both costs, ensuring only one mutable reference exists. Always verify gas coins are distinct from those being split or used in contract calls to avoid conflicts.
I hope you got solution for this huh?
You can’t use the same coin for both payment and gas. Fix:
- Split Gas First – Create a separate gas coin:
const [gasCoin] = tx.splitCoins(tx.object(primaryCoinId), [tx.pure(10_000_000)]); tx.setGasPayment([gasCoin]);
- Then Split Payment – Use the remaining balance for your NFT payment.
Key Rule:
✔ Each coin can only be used once per transaction.
Alternative: Use two separate coins (if available).
(Sui requires distinct coins for gas and payments to avoid conflicts.)
The error happens because you're trying to use the same coin object for two different things: splitting to make a payment and paying for gas. The system sees this as trying to use one object mutably twice in a single transaction, which isn't allowed.
You need a separate coin to pay for gas. Here's the fix:
-
Use a different gas coin: Find another coin in your wallet's list of SUI coins to specify as the
gasPayment
. Don't use theprimaryCoin
you're splitting. -
Or, merge coins first: If you only have one coin, you might need to merge some smaller coins into it first to create a separate gas coin. Then use one for the split/payment and the other for gas.
The key is that the coin you use for setGasPayment
must be completely separate from any coins you're splitting or using in the transaction's commands.
Bravo!!!
That error on Sui:
“Unable to process transaction – No valid gas coins found for the transaction”
means your wallet doesn’t currently have any SUI tokens that can be used as gas fees. Every transaction on Sui — whether sending tokens, minting NFTs, or interacting with dApps — requires a small amount of SUI to pay for gas.
🔍 Why It Happens
- No SUI balance: You don’t have any SUI in your wallet.
- Coin is too small: Sometimes SUI is “locked” in very tiny amounts (dust coins) that are not enough to cover gas.
- Wrong network: You may be on Testnet or Devnet but don’t have test SUI loaded.
- Wallet not refreshed: Rarely, the wallet UI lags behind and doesn’t recognize available coins.
✅ How to Fix It
If You’re on Mainnet
-
Get some SUI tokens
- Buy SUI from an exchange (Binance, KuCoin, OKX, etc.) and withdraw to your wallet.
- Or receive SUI from a friend/wallet that already has some.
-
Check for Coin Splitting
- Sometimes you have SUI, but it’s fragmented into unusable “dust.”
- Use the “Merge Coins” feature in Sui Wallet (found under your SU
-
Use a Faucet
-
Go to the official Sui faucet: https://faucet.sui.io
-
Or, on Discord (in the Sui Discord server), go to the #testnet-faucet channel and type:
!faucet <your_sui_address>
-
This will send you free testnet SUI.
-
-
Switch Networks Properly
- In your Sui Wallet extension → click profile icon → select Testnet or Devnet depending on where you’re working.
⚠️ Tip
Always keep a small reserve of SUI in your wallet for gas (like 0.05–0.1 SUI). If you send your entire balance out, you won’t have gas left to make the next transaction.
Do you want me to walk you through getting testnet SUI from the faucet right now, or are you running into this issue on mainnet with real tokens?
Do you know the answer?
Please log in and share it.
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.
- How to Maximize Profit Holding SUI: Sui Staking vs Liquid Staking615
- Why does BCS require exact field order for deserialization when Move structs have named fields?65
- Multiple Source Verification Errors" in Sui Move Module Publications - Automated Error Resolution55
- Sui Move Error - Unable to process transaction No valid gas coins found for the transaction419
- Sui Transaction Failing: Objects Reserved for Another Transaction410