kubernetes/kops · error
unable to parse version string: %q
Error message
unable to parse version string: %q
What it means
findContainerdVersionUrl parses the containerd version with semver.ParseTolerant before constructing the GitHub release URL. If the string is not a tolerable semantic version (missing numbers, garbage characters), the parse fails and this error is returned wrapping the raw version. It blocks building a release URL from an unusable version.
Source
Thrown at pkg/nodemodel/wellknownassets/containerd.go:76
version := fi.ValueOf(containerd.Version)
if version == "" {
return nil, fmt.Errorf("unable to find containerd version")
}
assetURL, err := findContainerdVersionUrl(arch, version)
if err != nil {
return nil, err
}
canonicalURL = assetURL.String()
}
return buildFileAsset(assetBuilder, canonicalURL, knownHash)
}
func findContainerdVersionUrl(arch architectures.Architecture, version string) (*url.URL, error) {
sv, err := semver.ParseTolerant(version)
if err != nil {
return nil, fmt.Errorf("unable to parse version string: %q", version)
}
if sv.LT(semver.MustParse("2.1.0")) {
return nil, fmt.Errorf("unsupported legacy containerd version: %q", version)
}
var u string
switch arch {
case architectures.ArchitectureAmd64:
u = fmt.Sprintf(containerdReleaseUrlAmd64, version, version)
case architectures.ArchitectureArm64:
u = fmt.Sprintf(containerdReleaseUrlArm64, version, version)
default:
return nil, fmt.Errorf("unknown arch: %q", arch)
}
return url.Parse(u)
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Set containerd.version to a clean semver value such as '2.1.0' (the 'v' prefix is tolerated)
- Strip any filename/suffix from the configured version so only 'X.Y.Z' remains
- Pin to a known containerd release listed on the containerd GitHub releases page
Example fix
// before containerd: version: containerd-2.1.0-linux-amd64 // after containerd: version: "2.1.0"
Defensive patterns
Strategy: validation
Validate before calling
if _, err := semver.ParseTolerant(containerdVersion); err != nil {
return fmt.Errorf("containerd.version %q is not a valid semver: %v", containerdVersion, err)
} Try / catch
asset, err := wellknownassets.FindContainerdAsset(ig, assetBuilder, arch)
if err != nil && strings.Contains(err.Error(), "unable to parse version string") {
return fmt.Errorf("containerd.version must look like X.Y.Z: %w", err)
} Prevention
- Store containerd version as a bare semver string, never a filename or tag
- Strip any leading/trailing whitespace when templating the version
- Add a semver regex check to your manifest lint pipeline
When it happens
Trigger: FindContainerdAsset falls back to version-based URL building with containerd.Version values like 'latest', 'v2.', '2.1', 'containerd-2.1.0', or any non-semver string.
Common situations: Users set version to a tag-style or marketing string instead of a release number; copy-paste of the full tarball filename into the version field; shell/templating substituting empty or partial values.
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
- cannot parse kubernetes version %q
- error parsing container runtime version %q: %w
- error parsing version %q for package %q
- error parsing version %q: %v
- failed to parse kubernetes version (%s): %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/9dcd52d6e3e5c914.
Report an issue: GitHub.