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 deliverGroupView on GitHub (pinned to 2736b63f8f)
Solutions
- Confirm --channelID is correct and the peer is joined to that channel
- Check the client identity satisfies the channel's readers/deliver ACL policy
- Read the status code in the message and peer logs; fix the underlying deliver rejection
- 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
- Double-check --channelID spelling
- Ensure the invoking identity has channel reader privileges
- Monitor peer uptime; avoid single-peer deliver waits in production
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
- can't read the block: %v
- timed out waiting for connection to deliver on all peers
- timed out waiting for txid on all peers
- received unexpected response type (%T) from %s
- proto: Marshal called with nil
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/84978be2f85d8f85.
Report an issue: GitHub.