{"record":{"id":"9c54ba26075b2e35","repo":"hyperledger/fabric","slug":"attempted-to-set-the-batch-timeout-to-a-non-positi","errorCode":null,"errorMessage":"Attempted to set the batch timeout to a non-positive value: %s","messagePattern":"Attempted to set the batch timeout to a non-positive value: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/channelconfig/orderer.go","lineNumber":237,"sourceCode":"\t\treturn fmt.Errorf(\"Attempted to set the batch size absolute max bytes to an invalid value: 0\")\n\t}\n\tif oc.protos.BatchSize.PreferredMaxBytes == 0 {\n\t\treturn fmt.Errorf(\"Attempted to set the batch size preferred max bytes to an invalid value: 0\")\n\t}\n\tif oc.protos.BatchSize.PreferredMaxBytes > oc.protos.BatchSize.AbsoluteMaxBytes {\n\t\treturn fmt.Errorf(\"Attempted to set the batch size preferred max bytes (%v) greater than the absolute max bytes (%v).\", oc.protos.BatchSize.PreferredMaxBytes, oc.protos.BatchSize.AbsoluteMaxBytes)\n\t}\n\treturn nil\n}\n\nfunc (oc *OrdererConfig) validateBatchTimeout() error {\n\tvar err error\n\toc.batchTimeout, err = time.ParseDuration(oc.protos.BatchTimeout.Timeout)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"Attempted to set the batch timeout to a invalid value: %s\", err)\n\t}\n\tif oc.batchTimeout <= 0 {\n\t\treturn fmt.Errorf(\"Attempted to set the batch timeout to a non-positive value: %s\", oc.batchTimeout)\n\t}\n\treturn nil\n}\n\nfunc (oc *OrdererConfig) validateAllOrgsHaveEndpoints() error {\n\tvar orgsMissingEndpoints []string\n\n\tfor _, org := range oc.Organizations() {\n\t\tif len(org.Endpoints()) == 0 {\n\t\t\torgsMissingEndpoints = append(orgsMissingEndpoints, org.Name())\n\t\t}\n\t}\n\n\tif len(orgsMissingEndpoints) > 0 {\n\t\treturn errors.Errorf(\"some orderer organizations endpoints are empty: %s\", orgsMissingEndpoints)\n\t}\n\n\treturn nil","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/channelconfig/orderer.go#L219-L255","documentation":"After successfully parsing the duration, validateBatchTimeout rejects non-positive values. A batch timeout of zero or negative would make the orderer cut batches immediately or behave nonsensically, so the config is rejected.","triggerScenarios":"BatchTimeout set to \"0s\", \"-1s\", or \"0\" (with valid unit) in configtx.yaml or in a channel config update transaction.","commonSituations":"Copying example configs and setting BatchTimeout to 0 to \"disable\" batching (misunderstanding it as a disable switch); template variables defaulting to zero values; scripting that computes the timeout and passes 0 or a negative.","solutions":["Set BatchTimeout to a positive duration, e.g. \"2s\" (Fabric default)","If you want faster block cutting, lower it toward e.g. \"250ms\" but keep it > 0","Regenerate the config with configtxgen"],"exampleFix":"# before (configtx.yaml)\nBatchTimeout: 0s\n# after\nBatchTimeout: 2s","handlingStrategy":"validation","validationCode":"d, err := time.ParseDuration(cfg.Orderer.BatchTimeout)\nif err != nil || d <= 0 {\n\treturn fmt.Errorf(\"BatchTimeout must be a positive duration, got %q\", cfg.Orderer.BatchTimeout)\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"non-positive value\") {\n\treturn fmt.Errorf(\"set BatchTimeout > 0 (Fabric default 2s): %w\", err)\n}","preventionTips":["Treat 0 as invalid for BatchTimeout — it is not a \"disable\" switch","Assert positive duration in config-generation scripts","Use the default \"2s\" unless you have measured reasons to change"],"tags":["hyperledger-fabric","configtx","validation","orderer"],"backgroundTag":"invalid-config-value","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"}