{"record":{"id":"a23f8e2fedbd9855","repo":"cloudflare/cloudflared","slug":"s-is-not-a-valid-url","errorCode":null,"errorMessage":"%s is not a valid URL","messagePattern":"(.+?) is not a valid URL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cloudflared/tunnel/ingress_subcommands.go","lineNumber":128,"sourceCode":"\t}\n\tconf = config.GetConfiguration()\n\tif conf.Source() == \"\" {\n\t\treturn nil, errors.New(\"No configuration file was found. Please create one, or use the --config flag to specify its filepath. You can use the help command to learn more about configuration files\")\n\t}\n\tfmt.Println(\"Validating rules from\", conf.Source())\n\treturn conf, nil\n}\n\n// testURLCommand checks which ingress rule matches the given URL.\nfunc testURLCommand(c *cli.Context) error {\n\trequestArg := c.Args().First()\n\tif requestArg == \"\" {\n\t\treturn errors.New(\"cloudflared tunnel rule expects a single argument, the URL to test\")\n\t}\n\n\trequestURL, err := url.Parse(requestArg)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s is not a valid URL\", requestArg)\n\t}\n\tif requestURL.Hostname() == \"\" && requestURL.Scheme == \"\" {\n\t\treturn fmt.Errorf(\"%s doesn't have a hostname, consider adding a scheme\", requestArg)\n\t}\n\n\tconf := config.GetConfiguration()\n\tfmt.Println(\"Using rules from\", conf.Source())\n\ting, err := ingress.ParseIngress(conf)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"Validation failed\")\n\t}\n\n\t_, i := ing.FindMatchingRule(requestURL.Hostname(), requestURL.Path)\n\tfmt.Printf(\"Matched rule #%d\\n\", i)\n\tfmt.Println(ing.Rules[i].MultiLineString())\n\treturn nil\n}\n","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cmd/cloudflared/tunnel/ingress_subcommands.go#L110-L146","documentation":"testURLCommand (backing `cloudflared tunnel ingress url <arg>`) parses the argument as a URL to test against ingress rules. If net/url.Parse fails on the argument, this error reports the argument as an invalid URL. It catches malformed inputs that cannot be parsed at all.","triggerScenarios":"Running `cloudflared tunnel ingress url <arg>` where url.Parse rejects the argument, e.g. it contains control characters or an unparseable malformed scheme.","commonSituations":"Shell quoting issues injecting stray characters into the argument; pasting a URL with invisible whitespace; passing an escaped or partially-encoded URL.","solutions":["Quote the URL argument in the shell to avoid stray characters: `cloudflared tunnel ingress url 'https://example.com'`","Use a well-formed URL with a scheme, e.g. `https://example.com/path`","If the argument parses but has no host/scheme, add `https://` in front (see the related 'doesn't have a hostname' error)"],"exampleFix":"// before\n$ cloudflared tunnel ingress url http://example.com?redirect=http://other.com&a=|b\n\n// after (quote the argument)\n$ cloudflared tunnel ingress url 'http://example.com?redirect=http://other.com&a=|b'","handlingStrategy":"validation","validationCode":"u, err := url.Parse(arg)\nif err != nil {\n    return fmt.Errorf(\"invalid URL %q: %w\", arg, err)\n}","typeGuard":"func isParsableURL(s string) bool { _, err := url.Parse(s); return err == nil }","tryCatchPattern":"_, err := url.Parse(requestArg)\nif err != nil {\n    return fmt.Errorf(\"cannot test %q: %w\", requestArg, err)\n}","preventionTips":["Always quote URL arguments in shell scripts","Strip whitespace/control characters from pasted URLs before passing them","Prefer full URLs with scheme and host when testing ingress rules"],"tags":["cli","url","ingress","validation"],"backgroundTag":"invalid-url-format","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}