{"record":{"id":"c0cd20edab8ebc7a","repo":"hyperledger/fabric","slug":"header-type-is-not-an-endorser-transaction","errorCode":null,"errorMessage":"header type is not an endorser transaction","messagePattern":"header type is not an endorser transaction","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gossip/privdata/coordinator.go","lineNumber":439,"sourceCode":"\t\tlogger.Warningf(\"Invalid payload: %s\", err)\n\t\treturn nil, err\n\t}\n\tif payload.Header == nil {\n\t\terr := errors.New(\"payload header is nil\")\n\t\tlogger.Warningf(\"Invalid tx: %s\", err)\n\t\treturn nil, err\n\t}\n\n\tchdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)\n\tif err != nil {\n\t\tlogger.Warningf(\"Invalid channel header: %s\", err)\n\t\treturn nil, err\n\t}\n\ttxInfo.channelID = chdr.ChannelId\n\ttxInfo.txID = chdr.TxId\n\n\tif chdr.Type != int32(common.HeaderType_ENDORSER_TRANSACTION) {\n\t\terr := errors.New(\"header type is not an endorser transaction\")\n\t\tlogger.Debugf(\"Invalid transaction type: %s\", err)\n\t\treturn nil, err\n\t}\n\n\trespPayload, err := protoutil.GetActionFromEnvelope(envBytes)\n\tif err != nil {\n\t\tlogger.Warningf(\"Failed obtaining action from envelope: %s\", err)\n\t\treturn nil, err\n\t}\n\n\ttx, err := protoutil.UnmarshalTransaction(payload.Data)\n\tif err != nil {\n\t\tlogger.Warningf(\"Invalid transaction in payload data for tx [%s]: %s\", chdr.TxId, err)\n\t\treturn nil, err\n\t}\n\n\tccActionPayload, err := protoutil.UnmarshalChaincodeActionPayload(tx.Actions[0].Payload)\n\tif err != nil {","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/gossip/privdata/coordinator.go#L421-L457","documentation":"This error comes from Hyperledger Fabric's gossip private-data coordinator. getTxInfoFromTransactionBytes parses a transaction envelope to extract channel ID and TXID for private-data retrieval, and it only accepts endorser transactions. When the unmarshaled common.Header has a type other than HeaderType_ENDORSER_TRANSACTION (e.g. configuration records), the parse is aborted because private data semantics only exist for endorser transactions.","triggerScenarios":"Feeding a non-endorser envelope (ConfigTx, CONFIG_UPDATE, PEER_RESOURCE_UPDATE) into the coordinator via getTxPvtdataInfoFromBlock — i.e. a block containing a non-transaction record, or corrupted ledger data where a non-tx record occupies a tx slot.","commonSituations":"Peers processing genesis/config blocks during bootstrap; corrupted ledger commit flags marking non-tx records as transactions; custom tooling that replays blocks or feeds envelopes through the coordinator incorrectly.","solutions":["Verify the block you feed contains only regular endorser transactions; skip records where the block metadata tx-filter marks them invalid/non-tx.","Run `peer node rebuild-dbs` or re-fetch the block from an orderer/peer if the ledger is corrupted.","Ensure chaincode/config transactions are not pushed through the private-data coordinator path in custom code.","Inspect the envelope with protoutil to confirm chdr.Type before calling private-data APIs."],"exampleFix":"// before: feeding all block envelopes blindly\ntxInfo, err := getTxInfoFromTransactionBytes(txEnvBytes)\n\n// after: guard by envelope type first\nchdr, _ := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)\nif chdr.Type != int32(common.HeaderType_ENDORSER_TRANSACTION) {\n    continue // skip non-endorser records\n}\ntxInfo, err := getTxInfoFromTransactionBytes(txEnvBytes)","handlingStrategy":"validation","validationCode":"chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)\nif err != nil {\n    return err\n}\nif chdr.Type != int32(common.HeaderType_ENDORSER_TRANSACTION) {\n    return errors.Errorf(\"skip: header type %s is not ENDORSER_TRANSACTION\", chdr.Type)\n}","typeGuard":"func isEndorserTransaction(chdr *common.ChannelHeader) bool {\n    return chdr != nil && chdr.Type == int32(common.HeaderType_ENDORSER_TRANSACTION)\n}","tryCatchPattern":"txInfo, err := getTxInfoFromTransactionBytes(envBytes)\nif err != nil {\n    if strings.Contains(err.Error(), \"header type is not an endorser transaction\") {\n        logger.Debugf(\"skipping non-endorser record\")\n        return nil // expected for config blocks\n    }\n    return err\n}","preventionTips":["Always check the block's tx-filter metadata before treating records as transactions.","Skip config/genesis blocks in pvt-data processing paths.","Validate envelopes with protoutil helpers before feeding them to the coordinator.","Keep ledger integrity — unexpected header types in tx slots usually mean corruption."],"tags":["fabric","ledger","block-processing","private-data"],"backgroundTag":"non-endorser-transaction-in-block","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}