{"record":{"id":"da92ff71321dbbe2","repo":"hyperledger/fabric","slug":"txid-s-s-exists","errorCode":null,"errorMessage":"txid: %s(%s) exists","messagePattern":"txid: (.+?)\\((.+?)\\) exists","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/transaction_contexts.go","lineNumber":45,"sourceCode":"\t\tcontexts: map[string]*TransactionContext{},\n\t}\n}\n\n// contextID creates a transaction identifier that is scoped to a channel.\nfunc contextID(channelID, txID string) string {\n\treturn channelID + txID\n}\n\n// Create creates a new TransactionContext for the specified channel and\n// transaction ID. An error is returned when a transaction context has already\n// been created for the specified channel and transaction ID.\nfunc (c *TransactionContexts) Create(txParams *ccprovider.TransactionParams) (*TransactionContext, error) {\n\tc.mutex.Lock()\n\tdefer c.mutex.Unlock()\n\n\tctxID := contextID(txParams.ChannelID, txParams.TxID)\n\tif c.contexts[ctxID] != nil {\n\t\treturn nil, errors.Errorf(\"txid: %s(%s) exists\", txParams.TxID, txParams.ChannelID)\n\t}\n\n\ttxctx := &TransactionContext{\n\t\tNamespaceID:          txParams.NamespaceID,\n\t\tChannelID:            txParams.ChannelID,\n\t\tSignedProp:           txParams.SignedProp,\n\t\tProposal:             txParams.Proposal,\n\t\tResponseNotifier:     make(chan *pb.ChaincodeMessage, 1),\n\t\tTXSimulator:          txParams.TXSimulator,\n\t\tHistoryQueryExecutor: txParams.HistoryQueryExecutor,\n\t\tCollectionStore:      txParams.CollectionStore,\n\t\tIsInitTransaction:    txParams.IsInitTransaction,\n\n\t\tqueryIteratorMap:    map[string]commonledger.ResultsIterator{},\n\t\tpendingQueryResults: map[string]*PendingQueryResult{},\n\t}\n\ttxctx.InitializeCollectionACLCache()\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/transaction_contexts.go#L27-L63","documentation":"TransactionContexts.Create refuses to create a transaction context when one already exists for the same channel+txid key. Each transaction may be processed only once concurrently; a duplicate context means the same transaction ID is being launched twice.","triggerScenarios":"A message with the same ChannelID+TxID is delivered to the chaincode handler while a context for it already exists — e.g., duplicate delivery of the same transaction by the Deliver service, or a client retrying with a reused txid.","commonSituations":"Replayed/retried transaction submission reusing the same transaction ID; eventing bugs delivering a transaction twice; a stuck previous invocation whose context was never removed (processTransaction never completed) blocking reuse.","solutions":["Retry the transaction with a freshly computed, unique transaction ID (let the SDK generate it)","Check for stuck pending transactions in peer logs; restart the peer if a context leaked","Verify no client-side code reuses a txid across submission retries","If duplicate delivery is suspected, inspect the ordering service/deliver client configuration"],"exampleFix":"// before: client retries with same txid\nsubmit(tx, txid)\nsubmit(tx, txid)  // -> txid exists\n// after\nsubmit(tx, newTxID())\nsubmit(tx, newTxID())  // on retry","handlingStrategy":"try-catch","validationCode":"// SDK-side: always generate a fresh txid\nif txID == \"\" || seenTxIDs[txID] { txID = computeNewTxID(creator, nonce) }","typeGuard":null,"tryCatchPattern":"if err := cc.Invoke(txParams); err != nil && strings.Contains(err.Error(), \"exists\") {\n    // regenerate txid and resubmit, or wait for the in-flight tx to complete\n}","preventionTips":["Never reuse transaction IDs across retries","Let the SDK generate txids from creator+nonce","Handle stuck transactions (timeout -> resubmit with new txid)","Check for duplicate delivery in event/replay tooling"],"tags":["transaction","duplicate","concurrency"],"backgroundTag":"duplicate-txid","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}