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
- Compare the block's metadata vs Data.Data length in the log to find who supplied the bad index
- Check block storage integrity; if corrupted, rebuild the ledger database or resync from an orderer/other peer
- Fix custom committer/test code to bounds-check txPosition before Validate
- 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
- Bounds-check txPosition derived from block metadata
- Detect truncated blocks by comparing envelope counts with metadata
- Keep orderer and peer Fabric versions compatible
- Resync from peers/orderers if block files are corrupted
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
- empty block
- no block header
- Invalid Block on channel [%s]. Header must be different from
- Block with id [%d] on channel [%s] does not have metadata. B
- too few arguments
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/8131a6403595e288.
Report an issue: GitHub.