{"record":{"id":"6e906b1012189aca","repo":"nats-io/nats-server","slug":"gateway-q-has-no-url","errorCode":null,"errorMessage":"gateway %q has no URL","messagePattern":"gateway %q has no URL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/gateway.go","lineNumber":324,"sourceCode":"func validateGatewayOptions(o *Options) error {\n\tif o.Gateway.Name == _EMPTY_ && o.Gateway.Port == 0 {\n\t\treturn nil\n\t}\n\tif o.Gateway.Name == _EMPTY_ {\n\t\treturn errors.New(\"gateway has no name\")\n\t}\n\tif strings.Contains(o.Gateway.Name, \" \") {\n\t\treturn ErrGatewayNameHasSpaces\n\t}\n\tif o.Gateway.Port == 0 {\n\t\treturn fmt.Errorf(\"gateway %q has no port specified (select -1 for random port)\", o.Gateway.Name)\n\t}\n\tfor i, g := range o.Gateway.Gateways {\n\t\tif g.Name == _EMPTY_ {\n\t\t\treturn fmt.Errorf(\"gateway in the list %d has no name\", i)\n\t\t}\n\t\tif len(g.URLs) == 0 {\n\t\t\treturn fmt.Errorf(\"gateway %q has no URL\", g.Name)\n\t\t}\n\t}\n\tif err := validatePinnedCerts(o.Gateway.TLSPinnedCerts); err != nil {\n\t\treturn fmt.Errorf(\"gateway %q: %v\", o.Gateway.Name, err)\n\t}\n\treturn nil\n}\n\n// Computes a hash of 6 characters for the name.\n// This will be used for routing of replies.\nfunc getGWHash(name string) []byte {\n\treturn []byte(getHashSize(name, gwHashLen))\n}\n\nfunc getOldHash(name string) []byte {\n\tsha := sha256.New()\n\tsha.Write([]byte(name))\n\tfullHash := []byte(fmt.Sprintf(\"%x\", sha.Sum(nil)))","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/gateway.go#L306-L342","documentation":"A listed remote gateway must have at least one URL to connect to; without URLs the server has nowhere to dial for that cluster. The error names the gateway (as configured) so the incomplete entry can be found.","triggerScenarios":"A gateway { gateways: [ { name: \"B\" } ] } entry with no urls array, or RemoteGatewayOpts with empty URLs, during validateGatewayOptions/validateOptions at startup.","commonSituations":"Config omits the urls key, service discovery failed to populate URLs in generated configs, or a DNS/templating step produced an empty URL list; typos like 'url' instead of 'urls' also leave URLs empty.","solutions":["Add at least one URL: gateway { name: \"B\", urls: [\"nats://host:7222\"] }","Check key spelling — the field is urls (array), not url","In code, append to RemoteGatewayOpts.URLs before calling server.New/ValidateOptions","If URLs come from discovery, log why the list resolved empty and add a fallback address"],"exampleFix":"// before\ngateways: [ { name: \"B\" } ]\n// after\ngateways: [ { name: \"B\", urls: [\"nats://b.example.com:7222\"] } ]","handlingStrategy":"validation","validationCode":"for i, g := range opts.Gateway.Gateways {\n    if g.Name != \"\" && len(g.URLs) == 0 { return fmt.Errorf(\"gateway %q missing urls\", g.Name) }\n}","typeGuard":null,"tryCatchPattern":"err := server.ValidateOptions(opts)\nif err != nil && strings.Contains(err.Error(), \"has no URL\") {\n    // populate URLs for the named gateway before starting\n}","preventionTips":["Always include at least one reachable seed URL per remote gateway","Watch for singular 'url' vs plural 'urls' key typos","Validate rendered configs with nats-server -t in CI"],"tags":["config","gateway","validation"],"backgroundTag":"missing-config-field","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}