{"record":{"id":"f55021d00cce36d0","repo":"hashicorp/nomad","slug":"nil-consul-config","errorCode":null,"errorMessage":"nil consul config","messagePattern":"nil consul config","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/consul/consul.go","lineNumber":87,"sourceCode":"\tpreflightCheckBaseInterval time.Duration\n}\n\n// ConsulClientFunc creates a new Consul client for the specific Consul config\ntype ConsulClientFunc func(config *config.ConsulConfig, logger hclog.Logger) (Client, error)\n\n// NodeGetter breaks a circular dependency between client/config.Config and this\n// package\ntype NodeGetter interface {\n\tGetNode() *structs.Node\n}\n\n// NewConsulClientFactory returns a ConsulClientFunc that closes over the\n// partition\nfunc NewConsulClientFactory(nodeGetter NodeGetter) ConsulClientFunc {\n\n\treturn func(config *config.ConsulConfig, logger hclog.Logger) (Client, error) {\n\t\tif config == nil {\n\t\t\treturn nil, fmt.Errorf(\"nil consul config\")\n\t\t}\n\n\t\tlogger = logger.Named(\"consul\").With(\"name\", config.Name)\n\n\t\tnode := nodeGetter.GetNode()\n\t\tpartition := node.Attributes[\"consul.partition\"]\n\t\tpreflightCheckTimeout := durationFromMeta(\n\t\t\tnode, \"consul.token_preflight_check.timeout\", time.Second*10)\n\t\tpreflightCheckBaseInterval := durationFromMeta(\n\t\t\tnode, \"consul.token_preflight_check.base\", time.Millisecond*500)\n\n\t\tc := &consulClient{\n\t\t\tconfig:                     config,\n\t\t\tlogger:                     logger,\n\t\t\tpartition:                  partition,\n\t\t\tpreflightCheckTimeout:      preflightCheckTimeout,\n\t\t\tpreflightCheckBaseInterval: preflightCheckBaseInterval,\n\t\t}","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/consul/consul.go#L69-L105","documentation":"NewConsulClientFactory returns a ConsulClientFunc that builds a Consul client from a *config.ConsulConfig. The factory immediately rejects a nil config because every later step (logger naming, partition lookup, API client construction) depends on fields of that config, and a nil dereference would panic instead of returning a clean error.","triggerScenarios":"Creating the Consul client with a nil *config.ConsulConfig — e.g. the client's config assembly produced no Consul stanza or the Consul config struct was dropped/omitted during config parsing before ConsulClientFunc is invoked.","commonSituations":"Running a Nomad client whose configuration omitted the entire `consul { }` block while Consul features are still enabled; a config merge/unmarshal bug that drops ConsulConfig; tests constructing the client directly without a Consul config.","solutions":["Add a `consul { ... }` stanza to the Nomad client agent config so a valid ConsulConfig is built","Check the config-loading code path for a bug that leaves ConsulConfig nil (e.g. a struct pointer never initialized after merge)","Upgrade Nomad if a known config-merge regression drops the Consul config; otherwise file an issue with the agent config","In tests, pass a valid config.ConsulConfig (even minimal) to the ConsulClientFunc"],"exampleFix":"// before\nclientFactory := consul.NewConsulClientFactory(nodeGetter)\nclient, err := clientFactory(nil, logger) // nil config\n// after\nccfg := &config.ConsulConfig{Name: \"default\", ServerServiceName: \"nomad\", ...}\nclient, err := clientFactory(ccfg, logger)","handlingStrategy":"validation","validationCode":"if cfg == nil {\n    return fmt.Errorf(\"consul client requires a non-nil *config.ConsulConfig\")\n}\nclient, err := consulFn(cfg, logger)","typeGuard":"func hasConsulConfig(cfg *config.ConsulConfig) bool { return cfg != nil }","tryCatchPattern":null,"preventionTips":["Always ship a `consul { }` block in client agent configs where Consul is used","Add a startup assertion that the assembled client config contains a non-nil ConsulConfig before initializing services","Cover config-merge code with tests that assert ConsulConfig survives merging","Fail fast at config-load time rather than at client-factory time"],"tags":["consul","config","nil-pointer","client-setup"],"backgroundTag":"nil-config-passed","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"}