hashicorp/nomad · error
failed to parse source URL %q: %v
Error message
failed to parse source URL %q: %v
What it means
getURL parses the artifact's GetterSource with url.Parse; when parsing fails (err != nil) it wraps the underlying error in a non-recoverable *Error carrying the artifact URL. Nomad throws this because the artifact fetcher cannot even construct a request if the source URL is malformed — the getter subprocess can never be launched. Recoverable is false so the artifact download will not be retried.
Source
Thrown at client/allocrunner/taskrunner/getter/util.go:49
)
var ErrSandboxEscape = errors.New("artifact includes symlink that resolves outside of sandbox")
func getURL(taskEnv interfaces.EnvReplacer, artifact *structs.TaskArtifact) (string, error) {
source := taskEnv.ReplaceEnv(artifact.GetterSource)
// fixup GitHub SSH URL such as git@github.com:hashicorp/nomad.git
gitSSH := false
if strings.HasPrefix(source, githubPrefixSSH) {
gitSSH = true
source = source[len(githubPrefixSSH):]
}
u, err := url.Parse(source)
if err != nil {
return "", &Error{
URL: artifact.GetterSource,
Err: fmt.Errorf("failed to parse source URL %q: %v", artifact.GetterSource, err),
Recoverable: false,
}
}
// build the URL by substituting as necessary
q := u.Query()
for k, v := range artifact.GetterOptions {
q.Set(k, taskEnv.ReplaceEnv(v))
}
u.RawQuery = q.Encode()
// add the prefix back if necessary
sourceURL := u.String()
if gitSSH {
sourceURL = fmt.Sprintf("%s%s", githubPrefixSSH, sourceURL)
}
return sourceURL, nilView on GitHub (pinned to 482b49bf1a)
Solutions
- Print and inspect the exact artifact source value in the job file for hidden control characters or bad percent-escapes
- Rewrite the source as a clean, properly quoted URL string (e.g. quote the value in HCL: source = "https://...")
- If the source is templated, validate the expanded value (e.g. printf %q | URL-check) before submitting the job
- Use consul template or nomad job inspect to see the rendered job and confirm the final source URL
Example fix
// before
artifact {
source = "https://example.com/artifact
v1.tar.gz"
}
// after
artifact {
source = "https://example.com/artifact-v1.tar.gz"
} Defensive patterns
Strategy: validation
Validate before calling
// validate artifact source before submitting the job
u, err := url.Parse(src)
if err != nil || src == "" {
return fmt.Errorf("invalid artifact source %q: %v", src, err)
} Try / catch
// on the client, this error is non-recoverable; catch in task-runner wrapper
if errors.Is(err, getterErrType) && !err.Recoverable {
// do not retry; fix job spec
} Prevention
- Quote artifact sources in HCL and avoid multi-line paste-ins
- Lint job files (nomad job validate) before submission
- Check rendered/templated sources with nomad job inspect
- Strip control characters from templated URLs
When it happens
Trigger: url.Parse returns an error for the TaskArtifact.GetterSource — e.g. an unescaped control character or invalid percent-encoding in the source string (url.Parse rejects raw non-ASCII control bytes; note most syntactically odd strings still parse, so this fires mainly on control chars/bad escapes)
Common situations: Paste-in artifact sources with stray whitespace/newlines or CR characters from copy-paste, shell interpolation inserting control characters, mangled YAML/HCL quoting, or templated sources where a variable expanded to a string containing invalid byte sequences
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- plugin not found
- wait config is nil or empty
- wait config is empty
- retry config is nil or empty
- fingerprint name cannot be empty
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/691488dd14ab7a0f.
Report an issue: GitHub.