{"record":{"id":"0bf8073b00cffb41","repo":"benbjohnson/litestream","slug":"invalid-nats-url-w","errorCode":null,"errorMessage":"invalid NATS URL: %w","messagePattern":"invalid NATS URL: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/litestream/main.go","lineNumber":1919,"sourceCode":"\n\t// Build replica.\n\tclient := webdav.NewReplicaClient()\n\tclient.URL = webdavURL\n\tclient.Username = username\n\tclient.Password = password\n\tclient.Path = path\n\n\treturn client, nil\n}\n\n// newNATSReplicaClientFromConfig returns a new instance of nats.ReplicaClient built from config.\nfunc newNATSReplicaClientFromConfig(c *ReplicaConfig, _ *litestream.Replica) (_ *nats.ReplicaClient, err error) {\n\t// Parse URL if provided to extract bucket name and server URL\n\tvar url, bucket string\n\tif c.URL != \"\" {\n\t\tscheme, host, bucketPath, err := litestream.ParseReplicaURL(c.URL)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid NATS URL: %w\", err)\n\t\t}\n\t\tif scheme != \"nats\" {\n\t\t\treturn nil, fmt.Errorf(\"invalid scheme for NATS replica: %s\", scheme)\n\t\t}\n\n\t\t// Reconstruct URL without bucket path\n\t\tif host != \"\" {\n\t\t\turl = fmt.Sprintf(\"nats://%s\", host)\n\t\t}\n\n\t\t// Extract bucket name from path\n\t\tif bucketPath != \"\" {\n\t\t\tbucket = strings.Trim(bucketPath, \"/\")\n\t\t}\n\t}\n\n\t// Use bucket from config if not extracted from URL\n\tif bucket == \"\" {","sourceCodeStart":1901,"sourceCodeEnd":1937,"githubUrl":"https://github.com/benbjohnson/litestream/blob/4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3/cmd/litestream/main.go#L1901-L1937","documentation":"newNATSReplicaClientFromConfig parses c.URL via litestream.ParseReplicaURL to extract the server host and bucket; if that parser returns an error (unparseable or wrong-shape URL), the failure is wrapped as 'invalid NATS URL: %w' so the underlying parse error is preserved.","triggerScenarios":"A nats replica whose 'url' cannot be parsed by ParseReplicaURL — e.g. missing scheme ('nats://'), control characters, or a URL that fails net/url parsing rules.","commonSituations":"Hand-edited config URLs with unescaped characters or spaces; leaving 'url:' with an empty-but-present value in some parsing paths; copy errors inserting a quote into the URL.","solutions":["Set a well-formed NATS URL like 'nats://nats.example.com:4222/mybucket' (host and bucket path)","Inspect the wrapped cause after 'invalid NATS URL:' in the log to see the exact parse failure","URL-encode special characters or remove them from the config value"],"exampleFix":"# before\n- type: nats\n  url: nats://nats.example.com :4222/bucket\n# after\n- type: nats\n  url: nats://nats.example.com:4222/bucket","handlingStrategy":"validation","validationCode":"if rep.Type == \"nats\" && rep.URL != \"\" {\n    if _, _, _, err := litestream.ParseReplicaURL(rep.URL); err != nil {\n        return fmt.Errorf(\"nats replica %s: bad url: %w\", rep.Name, err)\n    }\n}","typeGuard":"func validNATSURL(raw string) bool {\n    scheme, _, _, err := litestream.ParseReplicaURL(raw)\n    return err == nil && scheme == \"nats\"\n}","tryCatchPattern":"if _, err := newNATSReplicaClientFromConfig(cfg, rep); err != nil {\n    var cause error\n    if strings.HasPrefix(err.Error(), \"invalid NATS URL:\") {\n        // log full wrapped chain with %v / errors.Unwrap\n    }\n    _ = cause\n}","preventionTips":["Validate nats URLs with ParseReplicaURL before writing config","Avoid unescaped spaces/special chars in config URLs","Test the exact config file with litestream before restarts"],"tags":["config","nats","url","litestream"],"backgroundTag":"invalid-url-format","analyzedSha":"4ed7a308f6271ebfd2b0a6e4b70b03011a37e4a3","analyzedAt":"2026-09-06T18:29:25.564Z","contentChangedAt":"2026-09-06T18:29:25.564Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}