hyperledger/fabric · error

deliver completed with status (%s) before txid received

Error message

deliver completed with status (%s) before txid received

What it means

The deliver stream closed by sending a final DeliverResponse_Status (e.g. FORBIDDEN, NOT_FOUND, SERVICE_UNAVAILABLE) before the awaited txid appeared in any block. This indicates the deliver session ended prematurely rather than delivering the transaction event.

Source

Thrown at internal/peer/chaincode/common.go:746

			err = errors.WithMessagef(err, "error receiving from deliver filtered at %s", dc.Address)
			dg.setError(err)
			return
		}
		switch r := resp.Type.(type) {
		case *pb.DeliverResponse_FilteredBlock:
			filteredTransactions := r.FilteredBlock.FilteredTransactions
			for _, tx := range filteredTransactions {
				if tx.Txid == dg.TxID {
					logger.Infof("txid [%s] committed with status (%s) at %s", dg.TxID, tx.TxValidationCode, dc.Address)
					if tx.TxValidationCode != pb.TxValidationCode_VALID {
						err = errors.Errorf("transaction invalidated with status (%s)", tx.TxValidationCode)
						dg.setError(err)
					}
					return
				}
			}
		case *pb.DeliverResponse_Status:
			err = errors.Errorf("deliver completed with status (%s) before txid received", r.Status)
			dg.setError(err)
			return
		default:
			err = errors.Errorf("received unexpected response type (%T) from %s", r, dc.Address)
			dg.setError(err)
			return
		}
	}
}

// WaitForWG waits for the deliverGroup's wait group and closes
// the channel when ready
func (dg *DeliverGroup) WaitForWG(readyCh chan struct{}) {
	dg.wg.Wait()
	close(readyCh)
}

// setError serializes an error for the deliverGroup

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Confirm --channelID is correct and the peer is joined to that channel
  2. Check the client identity satisfies the channel's readers/deliver ACL policy
  3. Read the status code in the message and peer logs; fix the underlying deliver rejection
  4. Retry the wait after the peer recovers, or query commit status via an alternate peer

Example fix

// before
peer chaincode invoke -o orderer:7050 -C mychanel -n mycc ...  # typo'd channel
// after
peer chaincode invoke -o orderer:7050 -C mychannel -n mycc ...
Defensive patterns

Strategy: type-guard

Validate before calling

// pre-check channel membership and ACLs
if !isPeerJoinedToChannel(peer, channelID) { return fmt.Errorf("peer not joined to %s", channelID) }

Type guard

func isDeliverStatusError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "deliver completed with status (")
}

Try / catch

if isDeliverStatusError(err) {
    status := extractBetween(err.Error(), "status (", ")")
    // FORBIDDEN → fix ACLs/identity; NOT_FOUND → fix channel name; otherwise check peer health
}

Prevention

When it happens

Trigger: Peer's deliver service rejects or closes the stream — wrong channel name (NOT_FOUND), ACL denying the client's deliver role (FORBIDDEN), peer restarting, or deliver service unavailable — while ClientWait is still waiting for the txid.

Common situations: Typo in --channelID; client identity lacking the channel-readers ACL; peer outage mid-wait; TLS identity not enrolled for the channel.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/84978be2f85d8f85. Report an issue: GitHub.