hyperledger/fabric · warning

context finished before block retrieved

Error message

context finished before block retrieved

What it means

deliverBlocks waits on a select for the next block, context cancellation, or a consensus error. When ctx is canceled or times out while waiting for the iterator's next block, the handler returns INTERNAL_SERVER_ERROR wrapping ctx.Err() with this message.

Source

Thrown at common/deliver/deliver.go:310

			if number > chain.Reader().Height()-1 {
				logger.Warningf("[channel: %s] Block %d not found, block number greater than chain length bounds", chdr.ChannelId, number)
				return cb.Status_NOT_FOUND, nil
			}
		}

		var block *cb.Block
		var status cb.Status

		iterCh := make(chan struct{})
		go func() {
			block, status = cursor.Next()
			close(iterCh)
		}()

		select {
		case <-ctx.Done():
			logger.Debugf("Context canceled, aborting wait for next block")
			return cb.Status_INTERNAL_SERVER_ERROR, errors.Wrapf(ctx.Err(), "context finished before block retrieved")
		case <-erroredChan:
			// TODO, today, the only user of the errorChan is the orderer consensus implementations.  If the peer ever reports
			// this error, we will need to update this error message, possibly finding a way to signal what error text to return.
			logger.Warningf("Aborting deliver for request because the backing consensus implementation indicates an error")
			return cb.Status_SERVICE_UNAVAILABLE, nil
		case <-iterCh:
			// Iterator has set the block and status vars
		}

		if status != cb.Status_SUCCESS {
			logger.Warningf("[channel: %s] Error reading from channel, cause was: %v", chdr.ChannelId, status)
			return status, nil
		}

		// increment block number to support FAIL_IF_NOT_READY deliver behavior
		number++

		if err := accessControl.Evaluate(); err != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Increase the client's gRPC deadline/timeout for the deliver stream
  2. Seek to a valid, existing block height (e.g., oldest/newest) rather than waiting on an unproduced height
  3. Check orderer health (consensus, Raft leader) and network connectivity; retry with backoff

Example fix

// before
ctx := context.Background()
stream, _ := client.Deliver(ctx) // no deadline
// after
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
stream, _ := client.Deliver(ctx)
Defensive patterns

Strategy: try-catch

Validate before calling

if deadline, ok := ctx.Deadline(); ok && time.Until(deadline) < 30*time.Second {
    return errors.New("deliver deadline too short; extend client timeout")
}

Try / catch

status, err := deliverClient.Deliver(ctx, envelope)
if err != nil && strings.Contains(err.Error(), "context finished before block retrieved") {
    if errors.Is(err, context.DeadlineExceeded) {
        return retryWithLongerDeadline(ctx)
    }
    return err // explicit cancel
}

Prevention

When it happens

Trigger: Client context deadline exceeded or explicit cancel while the deliver stream is blocked waiting for the next block from the ledger iterator.

Common situations: Client-side gRPC deadline too short relative to block production rate; seek on a height that isn't produced for a long time; orderer slow to commit; network partitions.

Related errors


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