kubernetes/kops · error
invalid image source URL %q: %w
Error message
invalid image source URL %q: %w
What it means
For each configured sideload image, Run() parses image.Sources[0] with net/url. If url.Parse fails, nodeup wraps the parse error as "invalid image source URL". This almost always means the first source string is not a syntactically valid URL (control characters, malformed scheme, etc.).
Source
Thrown at upup/pkg/fi/nodeup/command.go:350
loader.Builders = append(loader.Builders, &networking.CalicoBuilder{NodeupModelContext: modelContext})
loader.Builders = append(loader.Builders, &networking.CiliumBuilder{NodeupModelContext: modelContext})
loader.Builders = append(loader.Builders, &networking.KindnetBuilder{NodeupModelContext: modelContext})
loader.Builders = append(loader.Builders, &networking.AmazonVPCRoutedENIBuilder{NodeupModelContext: modelContext})
loader.Builders = append(loader.Builders, &networking.KuberouterBuilder{NodeupModelContext: modelContext})
loader.Builders = append(loader.Builders, &model.BootstrapClientBuilder{NodeupModelContext: modelContext})
taskMap, err := loader.Build()
if err != nil {
return fmt.Errorf("error building loader: %v", err)
}
for _, image := range nodeupConfig.Images[architecture] {
if len(image.Sources) == 0 {
return fmt.Errorf("image has no sources: %v", image)
}
u, err := url.Parse(image.Sources[0])
if err != nil {
return fmt.Errorf("invalid image source URL %q: %w", image.Sources[0], err)
}
key := "SideloadImage/" + path.Base(u.Path)
if _, ok := taskMap[key]; ok {
return fmt.Errorf("duplicate image task %q", key)
}
taskMap[key] = &nodetasks.LoadImageTask{
Sources: image.Sources,
Hash: image.Hash,
}
}
var target fi.NodeupTarget
switch c.Target {
case "direct":
target = &local.LocalTarget{
CacheDir: c.CacheDir,
Cloud: cloud,View on GitHub (pinned to 4c8573c808)
Solutions
- Look at the quoted URL in the error and fix the malformed source in the NodeupConfig / cluster spec
- Remove placeholder text or unescaped characters and re-render the config with `kops update cluster`
- Validate image source URLs with `url.Parse` semantics (e.g. quick check in Go or curl) before committing custom images
- Ensure the registry mirror/proxy URL used in the cluster spec is a valid absolute URL
Example fix
// before
// "sources": ["registry.example.com/{{ .cluster }}/pause:3.9"]
// after (rendered)
// "sources": ["registry.example.com/mycluster/pause:3.9"] Defensive patterns
Strategy: validation
Validate before calling
if _, err := url.Parse(image.Sources[0]); err != nil {
return fmt.Errorf("image %q source %q is not a valid URL", image.Name, image.Sources[0])
} Type guard
func validImageSource(src string) bool {
u, err := url.Parse(src)
return err == nil && u.Scheme != "" && u.Host != ""
} Try / catch
if err := nodeupCmd.Run(ctx); err != nil {
if strings.Contains(err.Error(), "invalid image source URL") {
var urlErr error
errors.As(err, &urlErr)
log.Fatalf("fix image source in cluster spec: %v", urlErr)
}
return err
} Prevention
- Avoid raw template placeholders in image source URLs
- Sanitize/trim whitespace and newlines when templating registry URLs
- Validate URLs in CI before applying cluster spec changes
- Prefer mirror configs (containerd mirrors) over rewriting source URLs by hand
When it happens
Trigger: url.Parse(image.Sources[0]) returns an error for an entry in nodeupConfig.Images[architecture].
Common situations: Typo or unescaped characters in a custom image source; template substitution leaving placeholder text like {{ .registry }} in the URL; newline/whitespace corruption in generated nodeup config.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- image has no sources: %v
- duplicate image task %q
- error building context: %w
- building nodeConfig for instanceGroup: %w
- marshalling nodeupConfig: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/1f005cddb8ae9321.
Report an issue: GitHub.