{"record":{"id":"1af05d47827a3555","repo":"hashicorp/nomad","slug":"rpc-dial-timeout-must-be-greater-than-or-equal-to","errorCode":null,"errorMessage":"rpc.dial_timeout must be greater than or equal to zero","messagePattern":"rpc\\.dial_timeout must be greater than or equal to zero","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command/agent/config.go","lineNumber":974,"sourceCode":"func (r *RPCConfig) Validate() error {\n\tif r != nil {\n\t\tif r.AcceptBacklog < 0 {\n\t\t\treturn errors.New(\"rcp.accept_backlog interval must be greater than zero\")\n\t\t}\n\t\tif r.KeepAliveInterval < 0 {\n\t\t\treturn errors.New(\"rcp.keep_alive_interval must be greater than zero\")\n\t\t}\n\t\tif r.ConnectionWriteTimeout < 0 {\n\t\t\treturn errors.New(\"rcp.connection_write_timeout must be greater than zero\")\n\t\t}\n\t\tif r.StreamCloseTimeout < 0 {\n\t\t\treturn errors.New(\"rcp.stream_close_timeout must be greater than zero\")\n\t\t}\n\t\tif r.StreamOpenTimeout < 0 {\n\t\t\treturn errors.New(\"rcp.stream_open_timeout must be greater than zero\")\n\t\t}\n\t\tif r.DialTimeout < 0 {\n\t\t\treturn errors.New(\"rpc.dial_timeout must be greater than or equal to zero\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// RaftBoltConfig is used in servers to configure parameters of the boltdb\n// used for raft consensus.\ntype RaftBoltConfig struct {\n\t// NoFreelistSync toggles whether the underlying raft storage should sync its\n\t// freelist to disk within the bolt .db file. When disabled, IO performance\n\t// will be improved but at the expense of longer startup times.\n\t//\n\t// Default: false.\n\tNoFreelistSync bool `hcl:\"no_freelist_sync\"`\n}\n\nfunc (r *RaftBoltConfig) Copy() *RaftBoltConfig {","sourceCodeStart":956,"sourceCodeEnd":992,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/config.go#L956-L992","documentation":"The agent config validation rejects a negative `rpc.dial_timeout`. The RPC layer uses this duration to time outbound dial attempts, and a negative value is meaningless, so Validate() fails fast with this error at startup instead of producing confusing runtime dial failures. Zero is explicitly allowed (treated as no override / immediate default handling).","triggerScenarios":"Agent config contains `rpc { dial_timeout = <negative duration> }` (e.g. \"-5s\") and command/agent config parsing invokes the RPC block's Validate(), which checks `if r.DialTimeout < 0`.","commonSituations":"Typos with a leading minus sign in HCL/JSON config; scripts generating config by subtracting durations; copying a template and editing values incorrectly; unit tests injecting negative durations to check validation paths.","solutions":["Edit the agent config and set `rpc.dial_timeout` to a non-negative duration (e.g. \"10s\"), or remove the key to use the default.","If the value comes from automation, fix the script/templating so it cannot emit a negative duration.","If zero is desired behavior, set it explicitly to 0, which the validator accepts."],"exampleFix":"// before (config.hcl)\nrpc {\n  dial_timeout = \"-5s\"\n}\n\n// after\nrpc {\n  dial_timeout = \"10s\"\n}","handlingStrategy":"validation","validationCode":"d, err := time.ParseDuration(cfg.RPC.DialTimeout)\nif err != nil || d < 0 {\n    return fmt.Errorf(\"rpc.dial_timeout must be a non-negative duration, got %q\", cfg.RPC.DialTimeout)\n}","typeGuard":"func validDialTimeout(d time.Duration) bool { return d >= 0 }","tryCatchPattern":null,"preventionTips":["Never hand-write negative durations in config; template them from validated constants.","Add a pre-start config lint that asserts all rpc durations are >= 0.","Prefer omitting rpc.dial_timeout to use the default."],"tags":["config-validation","rpc","duration","startup"],"backgroundTag":"invalid-config-value","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}