{"record":{"id":"03be448710b47caa","repo":"hashicorp/nomad","slug":"unexpected-envoy-version-format-w","errorCode":null,"errorMessage":"unexpected envoy version format: %w","messagePattern":"unexpected envoy version format: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/taskrunner/envoy_version_hook.go","lineNumber":196,"sourceCode":"\n\tlatest, err := semver(versions[0])\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn strings.ReplaceAll(configured, envoy.VersionVar, latest), nil\n}\n\n// semver sanitizes the envoy version string coming from Consul into the format\n// used by the Envoy project when publishing images (i.e. proper semver). This\n// resulting string value does NOT contain the 'v' prefix for 2 reasons:\n//  1. the version library does not include the 'v'\n//  2. its plausible unofficial images use the 3 numbers without the prefix for\n//     tagging their own images\nfunc semver(chosen string) (string, error) {\n\tv, err := version.NewVersion(chosen)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"unexpected envoy version format: %w\", err)\n\t}\n\treturn v.String(), nil\n}\n","sourceCodeStart":178,"sourceCodeEnd":200,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/taskrunner/envoy_version_hook.go#L178-L200","documentation":"The semver helper normalizes the chosen Envoy version string using hashicorp/go-version. Version strings without a leading 'v' and unofficial 3-number tags are tolerated by design, but if version.NewVersion(chosen) fails outright, the version format is unrecognized and this error is returned (later wrapped by tweakImage callers).","triggerScenarios":"version.NewVersion(chosen) errors inside semver — chosen is empty, contains non-numeric/prerelease garbage, or a string like 'latest'/'stable' instead of a version like '1.28.0' or 'v1.28.0'.","commonSituations":"Consul reporting an unexpected or empty Envoy version; job image template interpolating to 'latest' or a digest; custom/enterprise Envoy image tags that aren't numeric versions; regression from Consul returning a new version scheme the Nomad version doesn't parse.","solutions":["Check the wrapped error text to see the offending version string from Consul.","Set an explicit, semver-parsable image (e.g. envoyproxy/envoy:v1.28.0) so the hook doesn't need to interpolate.","Upgrade Nomad (and/or Consul) if the reported version uses a format your Nomad version can't parse.","If running unofficial Envoy images, tag them as plain x.y.z (three numbers, optional 'v' prefix)."],"exampleFix":"// before\nimage: \"envoyproxy/envoy:latest\"\n// after\nimage: \"envoyproxy/envoy:v1.28.0\"","handlingStrategy":"type-guard","validationCode":"import \"github.com/hashicorp/go-version\"\n// validate any custom envoy version string before using it in an image\nif _, err := version.NewVersion(strings.TrimPrefix(chosen, \"v\")); err != nil {\n    return fmt.Errorf(\"invalid envoy version %q\", chosen)\n}","typeGuard":"func isEnvoySemver(s string) bool {\n    _, err := version.NewVersion(strings.TrimPrefix(s, \"v\"))\n    return err == nil\n}","tryCatchPattern":"image, err := tweakImage(taskImage, proxies)\nif err != nil {\n    var verErr error\n    if errors.As(err, &verErr) && strings.Contains(err.Error(), \"unexpected envoy version format\") {\n        image = fallbackEnvoyImage // e.g. envoyproxy/envoy:v1.28.0\n    }\n}","preventionTips":["Never tag or reference Envoy images as 'latest'/'stable'; use X.Y.Z.","Accept only numeric three-part versions for custom Envoy builds.","Upgrade Nomad if Consul starts reporting a new version format.","Validate version strings in CI before deploying connect-enabled jobs."],"tags":["nomad","envoy","semver","version-parsing"],"backgroundTag":"unexpected-envoy-version-format","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}