hashicorp/terraform · error

Error parsing URL

Error message

Error parsing URL: %s

What it means

Returned by the remote-shorthand detector when, after a subdir has been appended to the detected result ('<result>//<subDir>'), url.Parse fails on the combined string. The subdir join produces u.Path = old + '//' + subDir; if the result is not a valid URL the parse errors. The %s is the url.Parse error.

Solutions

  1. Sanitize the subdir portion of the source to valid URL path characters.
  2. Specify the source without a subdir first to confirm the base parses, then add '//subdir'.
  3. Use the fully-qualified form (git::https://...//subdir) to avoid detector ambiguity.

Example fix

# before (space in subdir)
source = "github.com/org/repo//my module"

# after
source = "github.com/org/repo//my-module"
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate that base + subdir parses before invoking the detector.
// func precheckRemoteWithSubdir(base, subdir string) error {
//     u, err := url.Parse(base)
//     if err != nil { return err }
//     u.Path += "//" + subdir
//     _, err = url.Parse(u.String())
//     return err
// }

Prevention

When it happens

Trigger: A detected remote source combined with a user subdir yields an invalid URL — typically because the subdir or the detected base contains characters that break URL parsing once concatenated.

Common situations: Subdir containing spaces/control chars; detector returned a result with an unexpected scheme; nested double-slash or encoding artifacts from copy-paste.

Related errors


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

Appendix: source

Thrown at internal/getmodules/moduleaddrs/detect_remote_shorthands.go:70

		var detectForce string
		detectForce, result = getForcedSourceType(result)
		result, detectSubdir := SplitPackageSubdir(result)

		// If we have a subdir from the detection, then prepend it to our
		// requested subdir.
		if detectSubdir != "" {
			if subDir != "" {
				subDir = filepath.Join(detectSubdir, subDir)
			} else {
				subDir = detectSubdir
			}
		}

		if subDir != "" {
			u, err := url.Parse(result)
			if err != nil {
				return "", fmt.Errorf("Error parsing URL: %s", err)
			}
			u.Path += "//" + subDir

			// a subdir may contain wildcards, but in order to support them we
			// have to ensure the path isn't escaped.
			u.RawPath = u.Path

			result = u.String()
		}

		// Preserve the forced getter if it exists. We try to use the
		// original set force first, followed by any force set by the
		// detector.
		if getForce != "" {
			result = fmt.Sprintf("%s::%s", getForce, result)
		} else if detectForce != "" {
			result = fmt.Sprintf("%s::%s", detectForce, result)
		}

View on GitHub (pinned to d32a084675)