hashicorp/terraform · error

URL is not a valid GCS URL

Error message

URL is not a valid GCS URL

What it means

Returned by detectGCS (detect_gcs.go:22) when the source string contains 'googleapis.com/' (so it looks like a GCS reference) but has fewer than 5 path segments after splitting on '/'. The detector expects the form googleapis.com/<version>/<bucket>/<object...> (at least version+bucket+object), so too few segments means the URL is structurally incomplete.

Source

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

package moduleaddrs

import (
	"fmt"
	"net/url"
	"strings"
)

// detectGCS detects strings that seem like schemeless references to
// Google Cloud Storage and translates them into URLs for the "gcs" getter.
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. Provide the full GCS path: googleapis.com/<api-version>/<bucket>/<object-or-prefix>, e.g. googleapis.com/storage/v1/my-bucket/modules/vpc.zip.
  2. If you intended a different source, switch to the explicit gcs:: URL form: gcs::https://www.googleapis.com/storage/v1/bucket/object.
  3. Verify the URL has at least four slashes' worth of segments (host/version/bucket/object).
  4. Use terraform init -from-module with a known-good GCS URL to confirm the format.

Example fix

# before
source = "googleapis.com/storage/v1/my-bucket"

# after — include the object/prefix segment
source = "googleapis.com/storage/v1/my-bucket/modules/vpc.zip"
Defensive patterns

Strategy: validation

Validate before calling

// Validate a GCS shorthand has all required segments before detection
func validGCSShorthand(src string) bool {
    if !strings.Contains(src, "googleapis.com/") {
        return true // not a GCS shorthand
    }
    return len(strings.Split(src, "/")) >= 5
}

Type guard

func isCompleteGCSURL(src string) bool {
    if !strings.Contains(src, "googleapis.com/") {
        return false
    }
    return len(strings.Split(src, "/")) >= 5
}

Prevention

When it happens

Trigger: A module source string referencing a GCS path via googleapis.com but missing required path components. detectGCS splits on '/', requires len(parts) >= 5 (host + version + bucket + at least one object segment), and otherwise returns this error.

Common situations: Writing source = "googleapis.com/storage/v1/my-bucket" (missing the object/path segment) or "googleapis.com/storage/v1" (missing bucket and object). Copy-paste of a partial GCS URL. Misremembering the expected GCS path shape.

Related errors


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