hashicorp/terraform · error

error parsing GCS URL: %s

Error message

error parsing GCS URL: %s

What it means

Returned by detectGCS (detect_gcs.go:32) when url.Parse fails on the https URL constructed from the split GCS path segments. After assembling https://www.googleapis.com/storage/<version>/<bucket>/<object>, net/url.Parse rejects it. In practice this is rare because the constructed URL is largely controlled, but malformed user-supplied segments (e.g. invalid characters) can break parsing.

Source

Thrown at internal/getmodules/moduleaddrs/detect_gcs.go:32

func detectGCS(src string) (string, bool, error) {
	if len(src) == 0 {
		return "", false, nil
	}

	if strings.Contains(src, "googleapis.com/") {
		parts := strings.Split(src, "/")
		if len(parts) < 5 {
			return "", false, fmt.Errorf(
				"URL is not a valid GCS URL")
		}
		version := parts[2]
		bucket := parts[3]
		object := strings.Join(parts[4:], "/")

		url, err := url.Parse(fmt.Sprintf("https://www.googleapis.com/storage/%s/%s/%s",
			version, bucket, object))
		if err != nil {
			return "", false, fmt.Errorf("error parsing GCS URL: %s", err)
		}

		return "gcs::" + url.String(), true, nil
	}

	return "", false, nil
}

View on GitHub (pinned to c9def3e214)

Solutions

  1. URL-encode any special characters in the bucket/object path segments of the source string.
  2. Simplify the source to ASCII-safe segment names and re-test.
  3. Prefer the explicit gcs::https://... form with a fully-formed, valid URL instead of relying on shorthand detection.
  4. Check the parse error detail in the message for the specific offending token.

Example fix

# before — object name has a space
source = "googleapis.com/storage/v1/my-bucket/my module.zip"

# after — encode special characters
source = "googleapis.com/storage/v1/my-bucket/my%20module.zip"
Defensive patterns

Strategy: validation

Validate before calling

// Pre-parse the assembled GCS URL to catch malformed segments
func gcsURLParses(src string) bool {
    if !strings.Contains(src, "googleapis.com/") {
        return true
    }
    parts := strings.Split(src, "/")
    if len(parts) < 5 {
        return false
    }
    u := fmt.Sprintf("https://www.googleapis.com/storage/%s/%s/%s",
        parts[2], parts[3], strings.Join(parts[4:], "/"))
    _, err := url.Parse(u)
    return err == nil
}

Type guard

func gcsURLParses(src string) bool {
    parts := strings.Split(src, "/")
    if len(parts) < 5 {
        return false
    }
    u := fmt.Sprintf("https://www.googleapis.com/storage/%s/%s/%s",
        parts[2], parts[3], strings.Join(parts[4:], "/"))
    _, err := url.Parse(u)
    return err == nil
}

Prevention

When it happens

Trigger: A GCS source string whose version/bucket/object segments contain characters that make the assembled URL invalid per net/url.Parse rules (e.g. spaces, control characters, or malformed percent-encoding).

Common situations: A bucket or object name with spaces or special characters not URL-encoded. A trailing fragment or query that confuses the parser. Cut-paste of a URL with stray characters. Non-ASCII object names.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/09f0ddde8a7bec94. Report an issue: GitHub.