pulumi/pulumi · error
module does not have semver compatible version
Error message
module does not have semver compatible version
What it means
normalizeVersion must produce a semver version for a provider dependency so it can be reported to the engine. When semver.ParseTolerant cannot parse the module's version string, this error is thrown. It happens when a module's resolved version is not a real semantic version (e.g. a module with no tagged release resolved to a bare revision, or a hand-edited go.mod with a bogus version).
Source
Thrown at sdk/go/pulumi-language-go/main.go:648
}
for _, path := range paths {
plugin, err := plugin.LoadPulumiPluginJSON(path)
if err != nil {
if os.IsNotExist(err) {
continue
}
return nil, err
}
return plugin, nil
}
return nil, nil
}
func normalizeVersion(version string) (string, error) {
v, err := semver.ParseTolerant(version)
if err != nil {
return "", errors.New("module does not have semver compatible version")
}
// psuedoversions are commits that don't have a corresponding tag at the specified git hash
// https://golang.org/cmd/go/#hdr-Pseudo_versions
// pulumi-aws v1.29.1-0.20200403140640-efb5e2a48a86 (first commit after 1.29.0 release)
if buildutil.IsPseudoVersion(version) {
// no prior tag means there was never a release build
if v.Major == 0 && v.Minor == 0 && v.Patch == 0 {
return "", errors.New("invalid pseduoversion with no prior tag")
}
// patch is typically bumped from the previous tag when using pseudo version
// downgrade the patch by 1 to make sure we match a release that exists
patch := v.Patch
if patch > 0 {
patch--
}
version = fmt.Sprintf("v%v.%v.%v", v.Major, v.Minor, patch)
}View on GitHub (pinned to 793f7b2e16)
Solutions
- Check go.mod for a `replace` directive pointing the provider at a local directory and pin a tagged version instead.
- Ensure the provider module has a valid semver git tag (e.g. v1.29.1) and re-run `go mod tidy`.
- If pulumi-plugin.json in the provider module sets a Version, make it valid semver.
- Use a pseudo-version pin (`go get module@commit`) rather than an untagged branch reference, so a parseable version resolves.
Example fix
// before (go.mod) replace github.com/pulumi/pulumi-aws/sdk => ../pulumi-aws/sdk // after require github.com/pulumi/pulumi-aws/sdk v1.29.1
Defensive patterns
Strategy: validation
Validate before calling
// shell, before pulumi up
ver=$(go list -m -f '{{.Version}}' github.com/pulumi/pulumi-aws/sdk)
semver_regex='^v?[0-9]+\.[0-9]+\.[0-9]+'
echo "$ver" | grep -Eq "$semver_regex" || echo "non-semver version: $ver" Prevention
- Avoid long-lived `replace` directives to local paths in committed go.mod.
- Only depend on provider SDK modules that have semver tags.
- Never set pulumi-plugin.json Version to non-semver values like "latest" or a branch name.
When it happens
Trigger: GetRequiredPackages -> getPackage -> normalizeVersion: m.Version (or pulumi-plugin.json Version, if set) cannot be parsed by semver.ParseTolerant.
Common situations: A pulumi provider dependency replaced with a local path (go.mod `replace` directive) so no version exists; a module fetched by branch/commit without tags; pulumi-plugin.json containing a non-semver Version like "main" or "latest".
Related errors
- invalid version %s
- invalid pseduoversion with no prior tag
- unknown resource type {typ}
- get provider version: %w
- must have a 'version' field of type string
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/605c6ba90e1b54da.
Report an issue: GitHub.