hashicorp/terraform · error

provider mirror returned invalid URL

Error message

provider mirror returned invalid URL %q: %s

What it means

From a 200 JSON response, the mirror's `archives[target].relative_url` is parsed with `url.Parse`. If parsing fails (control characters, invalid escapes, malformed URL), the error names the offending value and the parse error.

Solutions

  1. Inspect the `relative_url` value in the served JSON for illegal characters.
  2. Publish corrected URLs in the mirror index.
  3. Use absolute URLs if the mirror supports them, or ensure relative URLs are valid `path` references.

Example fix

// before
{"url":"C:\\providers\\aws.zip"}
// after
{"url":"hashicorp/aws/terraform-provider-aws_4.50.0_linux_amd64.zip"}
Defensive patterns

Strategy: validation

Validate before calling

// Validate the URL field before consuming it
u, err := url.Parse(archiveMeta.RelativeURL)
if err != nil {
    return fmt.Errorf("mirror served bad relative_url %q: %w", archiveMeta.RelativeURL, err)
}
if !u.IsAbs() && !strings.HasPrefix(u.Path, "/") {
    // ensure resolvable relative reference
}

Type guard

// isValidRelativeURL narrows to parseable URL strings
func isValidRelativeURL(s string) bool {
    _, err := url.Parse(s)
    return err == nil
}

Try / catch

rel, err := url.Parse(archiveMeta.RelativeURL)
if err != nil {
    // fall back to constructing the URL from a known pattern
    rel, _ = url.Parse(fmt.Sprintf("%s/%s/%s/%s.zip", provider.Namespace, provider.Type, version, target))
}

Prevention

When it happens

Trigger: `url.Parse(archiveMeta.RelativeURL)` returns a non-nil `err`; error wrapped at http_mirror_source.go:224.

Common situations: Mirror operator entered a bad `relative_url` (spaces, backslashes, control chars); encoding issue when serialising the JSON; mirror builds URLs by unescaped string concatenation.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/0f5a9def078ce5cd. Report an issue: GitHub.

Appendix: source

Thrown at internal/getproviders/http_mirror_source.go:224

	if err := dec.Decode(&bodyContent); err != nil {
		return PackageMeta{}, s.errQueryFailed(provider, fmt.Errorf("invalid response content from mirror server: %s", err))
	}

	archiveMeta, ok := bodyContent.Archives[target.String()]
	if !ok {
		return PackageMeta{}, ErrPlatformNotSupported{
			Provider:  provider,
			Version:   version,
			Platform:  target,
			MirrorURL: s.baseURL,
		}
	}

	relURL, err := url.Parse(archiveMeta.RelativeURL)
	if err != nil {
		return PackageMeta{}, s.errQueryFailed(
			provider,
			fmt.Errorf("provider mirror returned invalid URL %q: %s", archiveMeta.RelativeURL, err),
		)
	}
	absURL := finalURL.ResolveReference(relURL)

	ret := PackageMeta{
		Provider:       provider,
		Version:        version,
		TargetPlatform: target,

		Location: PackageHTTPURL(absURL.String()),
		Filename: path.Base(absURL.Path),
	}
	// A network mirror might not provide any hashes at all, in which case
	// the package has no source-defined authentication whatsoever.
	if len(archiveMeta.Hashes) > 0 {
		hashes := make([]Hash, 0, len(archiveMeta.Hashes))
		for _, hashStr := range archiveMeta.Hashes {
			hash, err := ParseHash(hashStr)

View on GitHub (pinned to d32a084675)