{"record":{"id":"75b04479865fe343","repo":"hyperledger/fabric","slug":"invalid-epoch-in-channelheader-expected-0-got","errorCode":null,"errorMessage":"invalid Epoch in ChannelHeader. Expected 0, got [%d]","messagePattern":"invalid Epoch in ChannelHeader\\. Expected 0, got \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/common/validation/msgvalidation.go","lineNumber":111,"sourceCode":"\t// validate the header type\n\tswitch common.HeaderType(cHdr.Type) {\n\tcase common.HeaderType_ENDORSER_TRANSACTION:\n\tcase common.HeaderType_CONFIG_UPDATE:\n\tcase common.HeaderType_CONFIG:\n\tdefault:\n\t\treturn errors.Errorf(\"invalid header type %s\", common.HeaderType(cHdr.Type))\n\t}\n\n\tputilsLogger.Debugf(\"validateChannelHeader info: header type %d\", common.HeaderType(cHdr.Type))\n\n\t// TODO: validate channelID in cHdr.ChannelID\n\n\t// Validate epoch in cHdr.Epoch\n\t// Currently we enforce that Epoch is 0.\n\t// TODO: This check will be modified once the Epoch management\n\t// will be in place.\n\tif cHdr.Epoch != 0 {\n\t\treturn errors.Errorf(\"invalid Epoch in ChannelHeader. Expected 0, got [%d]\", cHdr.Epoch)\n\t}\n\n\t// TODO: Validate version in cHdr.Version\n\n\treturn nil\n}\n\n// checks for a valid Header\nfunc validateCommonHeader(hdr *common.Header) (*common.ChannelHeader, *common.SignatureHeader, error) {\n\tif hdr == nil {\n\t\treturn nil, nil, errors.New(\"nil header\")\n\t}\n\n\tchdr, err := protoutil.UnmarshalChannelHeader(hdr.ChannelHeader)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/common/validation/msgvalidation.go#L93-L129","documentation":"validateChannelHeader currently enforces that ChannelHeader.Epoch is 0, since epoch management is not yet in place. If a transaction carries a non-zero Epoch it is rejected with this error reporting the received value.","triggerScenarios":"Submitting an envelope whose ChannelHeader.Epoch is set to any non-zero value — e.g. a client copying epoch values from config metadata, or hand-building headers with a hardcoded non-zero epoch.","commonSituations":"Custom clients attempting to implement epoch semantics that Fabric does not yet support; fixtures ported from other Fabric components where epoch is populated; SDK versions that set epoch from channel config views.","solutions":["Set ChannelHeader.Epoch to 0 when constructing transactions","Update the client/SDK code to stop copying epoch values from channel config into the header","If you believe epoch enforcement is the problem, verify all parties build headers consistently with Epoch=0","Check Fabric version notes: until epoch management lands, 0 is the only accepted value"],"exampleFix":"// before\nchdr := &common.ChannelHeader{Type: int32(common.HeaderType_ENDORSER_TRANSACTION), ChannelId: channelID, Epoch: epochFromConfig}\n// after\nchdr := &common.ChannelHeader{Type: int32(common.HeaderType_ENDORSER_TRANSACTION), ChannelId: channelID, Epoch: 0}","handlingStrategy":"validation","validationCode":"func epochIsZero(chdr *common.ChannelHeader) bool {\n    return chdr != nil && chdr.Epoch == 0\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.HasPrefix(err.Error(), \"invalid Epoch in ChannelHeader\") {\n    // set Epoch to 0 in the ChannelHeader and re-sign the payload\n}","preventionTips":["Hardcode Epoch: 0 in all transaction-header builders until epoch management ships","Do not copy epoch values from channel config metadata into transaction headers","Add a header-construction unit test asserting Epoch == 0"],"tags":["hyperledger-fabric","validation","epoch","channel-header"],"backgroundTag":"invalid-header-epoch","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"}