hyperledger/fabric · error

error unmarshalling LastConfig

Error message

error unmarshalling LastConfig

What it means

GetLastConfigIndexFromBlock reads the ORDERER block metadata entry. In the legacy path it unmarshals the entry first as cb.LastConfig; if those bytes are not a valid LastConfig protobuf, this wrapped error is returned. It means the signatures-metadata entry contents are corrupt or not in the expected legacy format.

Source

Thrown at protoutil/blockutils.go:197

}

// GetLastConfigIndexFromBlock retrieves the index of the last config block as
// encoded in the block metadata
func GetLastConfigIndexFromBlock(block *cb.Block) (uint64, error) {
	m, err := GetMetadataFromBlock(block, cb.BlockMetadataIndex_SIGNATURES)
	if err != nil {
		return 0, errors.WithMessage(err, "failed to retrieve metadata")
	}
	// TODO FAB-15864 Remove this fallback when we can stop supporting upgrade from pre-1.4.1 orderer
	if len(m.Value) == 0 {
		m, err := GetMetadataFromBlock(block, cb.BlockMetadataIndex_LAST_CONFIG)
		if err != nil {
			return 0, errors.WithMessage(err, "failed to retrieve metadata")
		}
		lc := &cb.LastConfig{}
		err = proto.Unmarshal(m.Value, lc)
		if err != nil {
			return 0, errors.Wrap(err, "error unmarshalling LastConfig")
		}
		return lc.Index, nil
	}

	obm := &cb.OrdererBlockMetadata{}
	err = proto.Unmarshal(m.Value, obm)
	if err != nil {
		return 0, errors.Wrap(err, "failed to unmarshal orderer block metadata")
	}
	return obm.LastConfig.Index, nil
}

// GetLastConfigIndexFromBlockOrPanic retrieves the index of the last config
// block as encoded in the block metadata, or panics on error
func GetLastConfigIndexFromBlockOrPanic(block *cb.Block) uint64 {
	index, err := GetLastConfigIndexFromBlock(block)
	if err != nil {
		panic(err)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Re-fetch the block from a healthy ordering node or peer ledger
  2. Validate metadata length and that the entry is non-empty before parsing
  3. Use GetLastConfigIndexFromBlockOrPanic only on blocks known to be valid; prefer the error-returning API in recovery code
  4. Rebuild the ledger (e.g. rejoin the channel) if block data is permanently corrupt

Example fix

// before
lc := &cb.LastConfig{}
err = proto.Unmarshal(m.Value, lc)
if err != nil {
    return 0, errors.Wrap(err, "error unmarshalling LastConfig")
}
// after
if len(m.Value) == 0 {
    return 0, errors.New("LAST_CONFIG metadata entry is empty")
}
lc := &cb.LastConfig{}
if err := proto.Unmarshal(m.Value, lc); err != nil {
    return 0, errors.Wrapf(err, "error unmarshalling LastConfig (%d bytes)", len(m.Value))
}
Defensive patterns

Strategy: validation

Validate before calling

func hasLastConfigEntry(block *cb.Block) bool {
    md := block.GetMetadata().GetMetadata()
    return len(md) >= int(cb.BlockMetadataIndex_LAST_CONFIG)+1 && len(md[cb.BlockMetadataIndex_LAST_CONFIG]) > 0
}

Type guard

func isParseableLastConfig(raw []byte) (*cb.LastConfig, bool) {
    lc := &cb.LastConfig{}
    if len(raw) == 0 || proto.Unmarshal(raw, lc) != nil {
        return nil, false
    }
    return lc, true
}

Try / catch

idx, err := GetLastConfigIndexFromBlock(block)
if err != nil {
    return fmt.Errorf("cannot locate last config in block %d: %w", block.GetHeader().GetNumber(), err)
}

Prevention

When it happens

Trigger: Calling GetLastConfigIndexFromBlock on a block whose metadata[BlockMetadataIndex_LAST_CONFIG] bytes fail proto.Unmarshal into cb.LastConfig — corrupt ledger data, or a metadata entry produced with a different layout.

Common situations: Reading blocks from a damaged file ledger, mixing Fabric versions where the LAST_CONFIG index semantics differ, or custom block producers writing non-standard metadata.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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