hyperledger/fabric · error

timeout expired while executing transaction

Error message

timeout expired while executing transaction

What it means

Returned by Handler.execute when waiting for the chaincode's response exceeds the configured execution timeout. The handler abandons waiting on txctx.ResponseNotifier, records an ExecuteTimeouts metric, and fails the transaction with ErrorExecutionTimeout ('timeout expired while executing transaction').

Source

Thrown at core/chaincode/handler.go:1449

	txctx, err := h.TXContexts.Create(txParams)
	if err != nil {
		return nil, err
	}
	defer h.TXContexts.Delete(msg.ChannelId, msg.Txid)

	if err = h.setChaincodeProposal(txParams.SignedProp, txParams.Proposal, msg); err != nil {
		return nil, err
	}

	h.serialSendAsync(msg)

	var ccresp *pb.ChaincodeMessage
	select {
	case ccresp = <-txctx.ResponseNotifier:
		// response is sent to user or calling chaincode. ChaincodeMessage_ERROR
		// are typically treated as error
	case <-time.After(timeout):
		err = errors.New(ErrorExecutionTimeout)
		h.Metrics.ExecuteTimeouts.With("chaincode", h.chaincodeID).Add(1)
	case <-h.streamDone():
		err = errors.New(ErrorStreamTerminated)
	}

	return ccresp, err
}

func (h *Handler) setChaincodeProposal(signedProp *pb.SignedProposal, prop *pb.Proposal, msg *pb.ChaincodeMessage) error {
	if prop != nil && signedProp == nil {
		return errors.New("failed getting proposal context. Signed proposal is nil")
	}
	// TODO: This doesn't make a lot of sense. Feels like both are required or
	// neither should be set. Check with a knowledgeable expert.
	if prop != nil {
		msg.Proposal = signedProp
	}
	return nil

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Increase core.chaincode.executetimeout in the peer configuration (e.g. 60s/120s).
  2. Profile and optimize the chaincode — move slow external I/O out of the transaction path.
  3. Check chaincode container logs/health for hangs, OOM kills, or crashes.
  4. Ensure the chaincode responds to every transaction; add deadline handling inside the chaincode.

Example fix

// before (core.yaml)
core.chaincode.executetimeout: 30s
// after
core.chaincode.executetimeout: 120s
Defensive patterns

Strategy: retry

Validate before calling

// size the timeout to the workload in core.yaml
core.chaincode.executetimeout: 120s // measure worst-case chaincode latency first

Try / catch

if err != nil && strings.Contains(err.Error(), "timeout expired") {
    // check chaincode logs, then resubmit with increased timeout
    return fmt.Errorf("transaction timed out; check chaincode performance: %w", err)
}

Prevention

When it happens

Trigger: The select in Handler.execute hits `case <-time.After(timeout)` because the chaincode container never sent a response message before the timeout (core.chaincode.executetimeout, default 30s) elapsed.

Common situations: Chaincode doing heavy computation or long external calls (HTTP, DB); chaincode container hung or OOM-killed; slow peer/CCaaS startup; core.chaincode.executetimeout set too low for the workload.

Understand the failure class

Related errors


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