{"record":{"id":"e6eb055ce0a6d0b0","repo":"hashicorp/terraform","slug":"registry-response-includes-invalid-download-url","errorCode":null,"errorMessage":"registry response includes invalid download URL: %s","messagePattern":"registry response includes invalid download URL: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getproviders/registry_client.go","lineNumber":285,"sourceCode":"\t\tif !match {\n\t\t\t// If the protocol version is not supported, try to find the closest\n\t\t\t// matching version.\n\t\t\tclosest, err := c.findClosestProtocolCompatibleVersion(ctx, provider, version)\n\t\t\tif err != nil {\n\t\t\t\treturn PackageMeta{}, err\n\t\t\t}\n\t\t\tprotoErr.Suggestion = closest\n\t\t\treturn PackageMeta{}, protoErr\n\t\t}\n\t}\n\n\tif body.OS != target.OS || body.Arch != target.Arch {\n\t\treturn PackageMeta{}, fmt.Errorf(\"registry response to request for %s archive has incorrect target %s\", target, Platform{body.OS, body.Arch})\n\t}\n\n\tdownloadURL, err := url.Parse(body.DownloadURL)\n\tif err != nil {\n\t\treturn PackageMeta{}, fmt.Errorf(\"registry response includes invalid download URL: %s\", err)\n\t}\n\tdownloadURL = resp.Request.URL.ResolveReference(downloadURL)\n\tif downloadURL.Scheme != \"http\" && downloadURL.Scheme != \"https\" {\n\t\treturn PackageMeta{}, fmt.Errorf(\"registry response includes invalid download URL: must use http or https scheme\")\n\t}\n\n\tret := PackageMeta{\n\t\tProvider:         provider,\n\t\tVersion:          version,\n\t\tProtocolVersions: protoVersions,\n\t\tTargetPlatform: Platform{\n\t\t\tOS:   body.OS,\n\t\t\tArch: body.Arch,\n\t\t},\n\t\tFilename: body.Filename,\n\t\tLocation: PackageHTTPURL(downloadURL.String()),\n\t\t// \"Authentication\" is populated below\n\t}","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/getproviders/registry_client.go#L267-L303","documentation":"Thrown when the registry's download_url field cannot be parsed as a URL. The download URL is later resolved against the request URL and required to be http/https.","triggerScenarios":"url.Parse(body.DownloadURL) returned a non-nil error (e.g. control characters, an unparseable scheme).","commonSituations":"Registry returns a download_url containing whitespace/control characters; a relative path with an unparseable form; corruption of the JSON field in transit.","solutions":["Report the malformed download_url to the registry operator","If self-hosting, ensure download_url is an absolute http(s) URL","Check for a misbehaving mirror or proxy that rewrites the field"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-validate a URL string parses cleanly.\nfunc parseableURL(s string) bool {\n    _, err := url.Parse(s)\n    return err == nil\n}","typeGuard":"func IsParseableURL(s string) bool {\n    _, err := url.Parse(s)\n    return err == nil\n}","tryCatchPattern":"if _, err := url.Parse(body.DownloadURL); err != nil {\n    return fmt.Errorf(\"registry returned an unparseable download_url: %w\", err)\n}","preventionTips":["Registries must publish absolute http(s) download URLs","Sanitize response fields of control characters before parsing"],"tags":["registry","url","download","provider","validation"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}