{"record":{"id":"daadd619817238c1","repo":"hyperledger/fabric","slug":"envelope-timestamp-s-is-more-than-s-apart-from-c","errorCode":null,"errorMessage":"envelope timestamp %s is more than %s apart from current server time %s","messagePattern":"envelope timestamp (.+?) is more than (.+?) apart from current server time (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/deliver/deliver.go","lineNumber":401,"sourceCode":"\terr = h.validateChannelHeader(ctx, chdr)\n\tif err != nil {\n\t\treturn nil, nil, nil, err\n\t}\n\n\treturn payload, chdr, shdr, nil\n}\n\nfunc (h *Handler) validateChannelHeader(ctx context.Context, chdr *cb.ChannelHeader) error {\n\tif chdr.GetTimestamp() == nil {\n\t\terr := errors.New(\"channel header in envelope must contain timestamp\")\n\t\treturn err\n\t}\n\n\tenvTime := time.Unix(chdr.GetTimestamp().Seconds, int64(chdr.GetTimestamp().Nanos)).UTC()\n\tserverTime := time.Now()\n\n\tif math.Abs(float64(serverTime.UnixNano()-envTime.UnixNano())) > float64(h.TimeWindow.Nanoseconds()) {\n\t\terr := errors.Errorf(\"envelope timestamp %s is more than %s apart from current server time %s\", envTime, h.TimeWindow, serverTime)\n\t\treturn err\n\t}\n\n\terr := h.BindingInspector.Inspect(ctx, chdr)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc noExpiration(_ []byte) time.Time {\n\treturn time.Time{}\n}\n","sourceCodeStart":383,"sourceCodeEnd":416,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/deliver/deliver.go#L383-L416","documentation":"validateChannelHeader compares the envelope timestamp to server time; if the absolute difference exceeds the handler's configured TimeWindow the request is rejected. This prevents replaying old SeekInfo envelopes and bounds clock-skew-sensitive authorization (context binding).","triggerScenarios":"Client clock is off (ahead or behind) by more than TimeWindow (default 15m) when the deliver request is signed and sent; a delayed/queued request that exceeds the window; a replayed captured envelope.","commonSituations":"VMs/containers with drifting clocks and no NTP; signing a request long before sending (batch scripts); cross-timezone/local-time bugs when computing timestamps in custom clients.","solutions":["Synchronize the client machine's clock with NTP (chrony/ntpd or host time sync for containers).","Re-sign and send the deliver request immediately before dispatch, not ahead of time.","Increase the orderer's deliver TimeWindow configuration if the deployment legitimately tolerates larger skew.","Compare client clock to orderer (e.g. orderer health/log timestamps) to quantify the skew."],"exampleFix":"// before (client signs at script start, sends later)\ntimestamp := scriptStartTime\n\n// after (sign just before send, with synced clock)\nrunNtpSync()\ntimestamp := protoutil.CurrentTimestampBytes()\nenv, _ := protoutil.CreateEnvelope(...); deliverNow(env)","handlingStrategy":"retry","validationCode":"skew := time.Since(time.Unix(chdr.GetTimestamp().Seconds, int64(chdr.GetTimestamp().Nanos)).UTC())\nif skew < 0 { skew = -skew }\nif skew > 15*time.Minute { resyncClockAndResignEnvelope() }","typeGuard":null,"tryCatchPattern":"for attempt := 0; attempt < 2; attempt++ {\n    err := sendDeliverRequest(env)\n    if err != nil && strings.Contains(err.Error(), \"apart from current server time\") {\n        syncClock(); env = resignWithFreshTimestamp(); continue\n    }\n    return err\n}","preventionTips":["Run NTP (chrony/ntpd) on all hosts and containers that sign deliver requests","Sign deliver envelopes immediately before sending","Monitor clock drift against orderer timestamps in health checks","Only widen orderer deliver TimeWindow deliberately and document it"],"tags":["hyperledger-fabric","deliver","clock-skew","timestamp"],"backgroundTag":"clock-skew-rejected","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"}