hyperledger/fabric · error

block has only %d transactions, but requested tx at position

Error message

block has only %d transactions, but requested tx at position %d

What it means

During commit-time validation, the builtin plugin validates the transaction at txPosition within block.Data.Data. This error is returned when the requested transaction index is out of range: the block contains fewer transactions than the requested position, indicating a miscomputed index by the caller or a truncated block.

Source

Thrown at core/handlers/validation/builtin/default_validation.go:61

//go:generate mockery -dir . -name TransactionValidator -case underscore -output mocks/
type TransactionValidator interface {
	Validate(block *common.Block, namespace string, txPosition int, actionPosition int, policy []byte) commonerrors.TxValidationError
}

func (v *DefaultValidation) Validate(block *common.Block, namespace string, txPosition int, actionPosition int, contextData ...validation.ContextDatum) error {
	if len(contextData) == 0 {
		logger.Panicf("Expected to receive policy bytes in context data")
	}

	serializedPolicy, isSerializedPolicy := contextData[0].(vp.SerializedPolicy)
	if !isSerializedPolicy {
		logger.Panicf("Expected to receive a serialized policy in the first context data")
	}
	if block == nil || block.Data == nil {
		return errors.New("empty block")
	}
	if txPosition >= len(block.Data.Data) {
		return errors.Errorf("block has only %d transactions, but requested tx at position %d", len(block.Data.Data), txPosition)
	}
	if block.Header == nil {
		return errors.Errorf("no block header")
	}

	var err error
	switch {
	case v.Capabilities.V2_0Validation():
		err = v.TxValidatorV2_0.Validate(block, namespace, txPosition, actionPosition, serializedPolicy.Bytes())

	case v.Capabilities.V1_3Validation():
		err = v.TxValidatorV1_3.Validate(block, namespace, txPosition, actionPosition, serializedPolicy.Bytes())

	case v.Capabilities.V1_2Validation():
		fallthrough

	default:
		err = v.TxValidatorV1_2.Validate(block, namespace, txPosition, actionPosition, serializedPolicy.Bytes())

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Compare the block's metadata vs Data.Data length in the log to find who supplied the bad index
  2. Check block storage integrity; if corrupted, rebuild the ledger database or resync from an orderer/other peer
  3. Fix custom committer/test code to bounds-check txPosition before Validate
  4. Verify all ordering nodes run compatible Fabric versions producing consistent block structure

Example fix

// before: index taken from metadata without bounds check
txPos := int(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER][0])
err := v.Validate(block, ns, txPos, 0, policy) // index may exceed len(Data.Data)
// after
if txPos < 0 || txPos >= len(block.Data.Data) {
    return fmt.Errorf("invalid tx position %d", txPos)
}
err := v.Validate(block, ns, txPos, 0, policy)
Defensive patterns

Strategy: validation

Validate before calling

if txPosition < 0 || txPosition >= len(block.Data.Data) {
    return fmt.Errorf("tx position %d out of range, block has %d txs", txPosition, len(block.Data.Data))
}
err := validator.Validate(block, namespace, txPosition, actionPosition, policyBytes)

Type guard

func txIndexValid(b *common.Block, pos int) bool {
    return b != nil && b.Data != nil && pos >= 0 && pos < len(b.Data.Data)
}

Try / catch

err := v.Validate(block, ns, txPos, actionPos, policy)
if err != nil && strings.HasPrefix(err.Error(), "block has only") {
    logger.Errorf("tx index out of range; verify committer index and block integrity: %v", err)
    return err
}

Prevention

When it happens

Trigger: Validate (committer path, TestErrorConversion, TestValidateBadInput) receives txPosition >= len(block.Data.Data), e.g. the committer computes the tx index from metadata that disagrees with the block's actual envelope count, or tests pass an index beyond a small fixture block.

Common situations: Truncated/corrupted block file on disk so Data has fewer envelopes than metadata claims; off-by-one in a custom committer or test; block produced by a misbehaving ordering node.

Related errors


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