hashicorp/terraform · error
error parsing Git SSH URL: %s
Error message
error parsing Git SSH URL: %s
What it means
Raised in detectSSH (internal/getmodules/moduleaddrs/detect_git.go:131) when normalizing an SCP-like SSH module source (e.g. git@github.com:org/repo.git?depth=1). After the colon-delimited path is split on '?', the query portion is parsed with url.ParseQuery; if that fails (typically invalid percent-encoding such as %zz), this error propagates up through detectGit. The first return value of detectGit is also flagged true so callers treat it as a hard error rather than 'not recognized'.
Source
Thrown at internal/getmodules/moduleaddrs/detect_git.go:131
}
user := matched[1]
host := matched[2]
path := matched[3]
qidx := strings.Index(path, "?")
if qidx == -1 {
qidx = len(path)
}
var u url.URL
u.Scheme = "ssh"
u.User = url.User(user)
u.Host = host
u.Path = path[0:qidx]
if qidx < len(path) {
q, err := url.ParseQuery(path[qidx+1:])
if err != nil {
return nil, fmt.Errorf("error parsing Git SSH URL: %s", err)
}
u.RawQuery = q.Encode()
}
return &u, nil
}
View on GitHub (pinned to c9def3e214)
Solutions
- Inspect the '?' portion of the SSH source string and fix or remove any invalid percent-encoded sequences (e.g. replace %zz with %25zz or drop the bad param).
- Percent-encode any literal '%' in query parameters as %25 before embedding them in the module source.
- Switch from SCP shorthand to a full ssh:// URL (ssh://git@example.com/org/repo.git?depth=1), which is parsed more leniently and avoids the SCP-path query extraction.
- Drop unnecessary query parameters and rely on go-getter defaults.
Example fix
// before
module "x" { source = "git@github.com:org/repo.git?depth=%zz" }
// after
module "x" { source = "git@github.com:org/repo.git?depth=1" } Defensive patterns
Strategy: validation
Validate before calling
// Validate the query string of an SCP-style SSH source before detection.
func validSSHQuery(src string) error {
q := src
if i := strings.Index(src, "?"); i != -1 {
q = src[i+1:]
if i2 := strings.Index(q, "#"); i2 != -1 {
q = q[:i2]
}
}
if q == "" {
return nil
}
if _, err := url.ParseQuery(q); err != nil {
return fmt.Errorf("invalid SSH query string %q: %w", q, err)
}
return nil
} Try / catch
// detectGit-style errors surface as a normal Go error; branch on it.
result, ok, err := detectGit(src)
if err != nil {
// src matched the SSH pattern but its query was malformed;
// fix/encode the source and retry, do not silently ignore.
return fmt.Errorf("module source %q is not a valid SSH URL: %w", src, err)
} Prevention
- Prefer full ssh:// URLs over SCP shorthand when query parameters are needed.
- Always percent-encode literal '%' as %25 inside query strings.
- In CI, render module sources from a template after URL-encoding parameter values.
When it happens
Trigger: A module source string matching the SSH pattern (user@host:path) whose query string after '?' contains an invalid percent-escape or malformed key=value pair, e.g. git@example.com:org/repo.git?ref=%zz or git@host:repo?foo===bar. url.ParseQuery rejects bad escapes and bad syntax.
Common situations: A developer copies a git clone URL with query args (depth, ref, sshkey) and accidentally includes a literal '%' that is not a valid hex escape; CI templating that injects unescaped tokens into the query string; Windows users pasting URLs with stray characters.
Related errors
- URL is not a valid GCS URL
- error parsing GCS URL: %s
- GitHub URLs should be github.com/username/repo
- error parsing GitHub URL: %s
- error parsing BitBucket URL: %s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/3ecf51d6dead8a02.
Report an issue: GitHub.