Sui.

Publication

Partagez vos connaissances.

Prime+15

Xavier.eth.
Jun 27, 2025
Questions et Réponses avec des Experts

Échec de la transaction Sui : objets réservés pour une autre transaction

Je rencontre un problème persistant JsonRpcErrorlorsque j'essaie d'exécuter des transactions sur Sui. L'erreur indique que les objets sont réservés pour une autre transaction, même si j'ai implémenté un traitement séquentiel des transactions avec des retards.

JsonRpcError: Failed to sign transaction by a quorum of validators because one or more of its objects is reserved for another transaction. Other transactions locking these objects:
- AV7coSQHWg5vN3S47xada6UiZGW54xxUNhRv1QUPqWK (stake 33.83)
    - 0x1c20f15cbe780ee7586a2df90c1ab70861ca77a15970bea8702a8cf97bd3eed9
    - 0x1c20f15cbe780ee7586a2df90c1ab70861ca77a15970bea8702a8cf97bd3eed9
    - 0x1c20f15cbe780ee7586a2df90c1ab70861ca77a15970bea8702a8cf97bd3eed9

J'ai essayé :

  • Exécution séquentielle des transactions (en attente de la fin de la transaction précédente)
  • Ajout de délais de 3 secondes entre les transactions

Et j'obtiens toujours la même erreur.

Utilisation de Sui RPC pour la soumission des transactions. Le même identifiant d'objet apparaît plusieurs fois dans la liste de verrouillage. Une erreur se produit même avec un séquençage minutieux des transactions.

  1. Qu'est-ce qui fait que les objets sont « réservés » pour d'autres transactions ?
  2. Comment puis-je vérifier correctement si un objet est disponible avant de l'utiliser dans une transaction ?
  3. Existe-t-il des bonnes pratiques pour gérer les verrous d'objets dans Sui ?
  4. Cela pourrait-il être lié au calendrier de finalité de la transaction ?

Quelqu'un a-t-il déjà rencontré ce problème ? Toute information sur la gestion appropriée des objets dans les transactions Sui serait grandement appréciée !

  • Sui
  • Transaction Processing
  • Move
4
10
Partager
Commentaires
.

Réponses

10
harry phan.
Jun 30 2025, 15:00

Cette erreur se produit si vous essayez d'exécuter deux transactions simultanément (par exemple, en démarrer une avant la fin de la précédente). Si vous réessayez d'exécuter la transaction de publication, sans exécuter une autre transaction avant ou en même temps, elle devrait réussir. Vous devrez peut-être aussi vous procurer plus d'essence au robinet (ou attendre un jour, le temps que l'époque change, pour que les objets soient déverrouillés)

Lorsque vous exécutez une transaction impliquant des objets appartenant à votre adresse (comme les objets à gaz), les validateurs réservent la dernière version de l'objet à utiliser pour la transaction qu'il signe. Si vous essayez d'exécuter deux transactions simultanément et qu'elles font référence au même objet, elles se feront concurrence pour les signatures des validateurs. Dans le cas heureux, l'une des transactions gagne et s'exécute, tandis que l'autre ne parvient pas à obtenir suffisamment de signatures. Dans le cas malheureux, les deux transactions peuvent ne pas obtenir suffisamment de signatures (si les deux ont obtenu plus d'un tiers des signatures du validateur, aucune ne peut obtenir plus des deux tiers, ce qui est le seuil), c'est ce qu'on appelle une équivoque, et à partir de ce moment, les objets qui ont été entrés dans les deux transactions ne peuvent plus être utilisés pour aucune autre transaction.

À la fin de l'époque (ils durent environ une journée — vous pouvez vérifier la progression jusqu'au prochain changement d'époque sur https://suiexplorer.com), tous les verrous sont libérés, vous pouvez donc réutiliser les objets, mais si vous n'avez pas changé d'époque depuis votre dernière tentative, vous devrez vous procurer plus de gaz.

12
Commentaires
.
0xduckmove.
Jun 30 2025, 07:04

Hé, vous essayez de faire une transaction trop rapidement et les objets ont été verrouillés.

Essayez d'envoyer une transaction avec les mêmes objets à la fois. Si vous envoyez deux transactions, certains validateurs peuvent accepter la première, d'autres pourraient accepter la seconde et vos objets seront bloqués car chaque transaction nécessite 66,7 % de validateurs et vous n'en obtenez peut-être que 50 %.

=> attendez que l'époque soit réinitialisée, c'est bientôt

Pour en savoir plus : https://forums.sui.io/t/beginner-tutorial-error-when-deploying-simple-sui-package/44842

6
Commentaires
.
Owen.
Owen4662
Jun 30 2025, 11:03

Sui utilise uncontrôle de simultanéité optimiste, ce qui signifie que les objets sont verrouillés lorsqu'ils sont utilisés dans une transaction jusqu'à ce que cette transaction soit finalisée ou expire.

Même si vous attendez 3 secondes entre les transactions, si la précédente n'a pas été finalisée, l'objet reste verrouillé. Cela signifie que la transaction est toujours en attente et qu'elle détient un accès exclusif à l'objet.


Comment vérifier si un objet est disponible

Utilisez la méthode Sui RPC :

sui_getObject

Vérifiez la réponse pour "status": "Locked"ou"owner": "locked".

Exemple de demande :

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "sui_getObject",
  "params": ["0x...object_id..."]
}

S'il est verrouillé, attendez plus longtemps et réessayez plus tard.

5
Commentaires
.
MiniBob.
Jun 30 2025, 11:50

L'erreur signifie que les objets utilisés par votre transaction sont toujours bloqués par des transactions précédentes qui n'ont pas encore été finalisées. Malgré les retards, les objets restent réservés jusqu'à ce que ces transactions soient effectuées en chaîne.

Pour corriger :

  1. Vérifiez toujours que les transactions précédentes impliquant les objets ont été entièrement finalisées avant de les réutiliser.
  2. Vérifiez l'état des objets via Sui RPC pour vous assurer qu'ils sont déverrouillés.
  3. Évitez d'envoyer des transactions parallèles ou rapides sur les mêmes objets.
  4. Mettez en œuvre de nouvelles tentatives avec des contrôles d'annulation et de finalité au lieu de délais fixes.

Ce verrouillage empêche les mises à jour contradictoires et est normal dans le modèle d'objet de Sui. JsonRpcErrorUn séquençage et une confirmation de finalité appropriés sont essentiels pour éviter.

4
Commentaires
.
BigDev.
Aug 15 2025, 16:24

Cette erreur signifie que les objets que vous utilisez sont toujours bloqués par des transactions antérieures qui n'ont pas encore été finalisées. Même en cas de retard, Sui les réserve jusqu'à ce que la chaîne confirme l'achèvement.

Pour résoudre ce problème, assurez-vous que toutes les transactions précédentes utilisant ces objets sont entièrement finalisées avant de les réutiliser. Vous pouvez vérifier leur statut via Sui RPC pour voir s'ils sont déverrouillés. Évitez d'envoyer des transactions multiples ou rapides impliquant les mêmes objets. Au lieu de vous fier à des délais fixes, utilisez les nouvelles tentatives avec annulation et confirmez le caractère définitif avant de réessayer.

Ce verrouillage fait partie de la façon dont Sui garantit la sécurité des mises à jour. Un séquençage et une finalité de vérification appropriés sont donc le moyen d'éviter JSONRPCEerror

2
Commentaires
.
0xF1RTYB00B5.
Sep 18 2025, 16:25

That’s a great debugging question — I’ve run into this exact issue before when building staking flows on Sui. Let me answer in detail, step-by-step, from my perspective using Sui daily.


🔍 Why objects get “reserved” in Sui

In Sui, every transaction consumes specific object versions. Once you submit a transaction that references an object, the network puts a lock on that object version until the transaction is finalized (committed or fails).

So when you see:

JsonRpcError: Failed to sign transaction ... one or more of its objects is reserved

it means:

  • The object version you’re trying to use is still “in flight” (reserved by another PTB),
  • Or you’re re-using an outdated version without refreshing from the fullnode,
  • Or the validator quorum hasn’t yet reached finality for the first transaction.

That’s why the same objectId shows multiple times in the lock list — you’re trying to consume the same locked version repeatedly.


✅ How I check object availability before using

I always follow these steps:

  1. After each transaction, re-fetch fresh object refs before building the next transaction block.

    const fresh = await provider.getObject({
      id: "0x1c20f15cbe780ee...",
      options: { showOwner: true, showPreviousTransaction: true, showContent: true },
    });
    const version = fresh.data.version; // must use this version in the next PTB
    
  2. Wait for local execution / finality when submitting. Always request WaitForLocalExecution in your signAndExecuteTransactionBlock. This ensures the object is unlocked before you try to use it again.

    const res = await signer.signAndExecuteTransactionBlock({
      transactionBlock: tx,
      requestType: "WaitForLocalExecution",
    });
    
  3. Implement a retry with exponential backoff when conflicts occur. Even with sequencing, there are cases where the fullnode lags. I use a submitWithRetry wrapper (like the one I showed earlier) that catches Object version mismatch and retries after re-fetching the object.


⚡ Best practices for handling object locks

  • Never reuse old object references. Always fetch the latest state from the RPC before constructing each PTB.
  • Design with parallelism in mind. If multiple independent flows need the same object, shard state across multiple owned objects (avoid a single global shared object).
  • Batch operations when possible. Use a single TransactionBlock with multiple Move calls instead of sending sequential transactions that lock the same object repeatedly.
  • Add backoff + retries. I usually back off 100ms, 200ms, 400ms, 800ms … up to ~3s before giving up.
  • Use checkpoints/finality awareness. Remember: an object isn’t truly free until the checkpoint is committed.

⏱️ Relation to finality timing

Yes, this is directly related. Even after a transaction appears “executed”, the object may remain reserved until:

  • The local fullnode confirms execution,
  • The consensus checkpoint includes it,
  • The version updates propagate across validators.

That’s why adding a blind 3-second delay isn’t reliable — network conditions and validator lag can extend this. The right way is fetch-after-execution instead of sleeping.


🛠️ Example: Safe sequential staking

Here’s how I do it in code (simplified):

async function safeStake(signer, validatorAddr, stakeAmountMist, stakeObjectId) {
  let attempt = 0;
  while (attempt < 5) {
    try {
      // 1. Fetch latest object version
      const obj = await provider.getObject({ id: stakeObjectId, options: { showOwner: true } });
      const version = obj.data.version;

      // 2. Build PTB with fresh version
      const tx = new TransactionBlock();
      tx.moveCall({
        target: "0x2::staking::request_add_stake",
        arguments: [tx.pure(validatorAddr), tx.pure(stakeAmountMist.toString())],
        typeArguments: [],
      });

      // 3. Execute with finality wait
      const res = await signer.signAndExecuteTransactionBlock({
        transactionBlock: tx,
        requestType: "WaitForLocalExecution",
      });

      console.log("✅ success:", res.digest);
      return res;
    } catch (e) {
      if (e.message.includes("reserved") || e.message.includes("Object version mismatch")) {
        attempt++;
        const backoff = 200 * 2 ** attempt;
        console.warn(`conflict, retrying in ${backoff}ms`);
        await new Promise(r => setTimeout(r, backoff));
        continue;
      }
      throw e;
    }
  }
  throw new Error("failed after retries");
}

This ensures:

  • I always use the latest object version,
  • I wait for finality,
  • I retry on transient lock errors.

🧩 TL;DR

  • Cause: Object locks happen because an object version is still reserved by an in-flight transaction.
  • Fix: Always re-fetch latest object versions, wait for local execution, and retry on conflicts.
  • Best practice: Shard state, batch operations, and use retries/backoff rather than fixed sleeps.
  • Yes, finality timing matters. Blind delays won’t solve it — confirmation checks + re-fetching will.
0
Commentaires
.

Connaissez-vous la réponse ?

Veuillez vous connecter et la partager.