{"record":{"id":"515edc044804f6bb","repo":"router-for-me/CLIProxyAPI","slug":"release-tag-q-resolves-version-q-want-q","errorCode":null,"errorMessage":"release-tag %q resolves version %q, want %q","messagePattern":"release-tag %q resolves version %q, want %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginstore/manifest.go","lineNumber":142,"sourceCode":"\t\t\treturn validatePinnedArtifactURLs(plan.Artifacts)\n\t\t}\n\t\treturn validateManifestSourceURL(m.SourceURL)\n\tcase InstallTypeGitHubRelease:\n\t\treleaseTag := strings.TrimSpace(m.ReleaseTag)\n\t\tif releaseTag == \"\" {\n\t\t\treturn fmt.Errorf(\"missing required field release-tag\")\n\t\t}\n\t\tplugin := m.Plugin()\n\t\tplugin.Install = InstallPlan{Type: InstallTypeGitHubRelease}\n\t\tif errValidate := ValidatePlugin(plugin); errValidate != nil {\n\t\t\treturn errValidate\n\t\t}\n\t\treleaseVersion, errVersion := ReleaseVersion(Release{TagName: releaseTag})\n\t\tif errVersion != nil {\n\t\t\treturn errVersion\n\t\t}\n\t\tif releaseVersion != normalizeVersion(version) {\n\t\t\treturn fmt.Errorf(\"release-tag %q resolves version %q, want %q\", releaseTag, releaseVersion, normalizeVersion(version))\n\t\t}\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"unsupported install type %q\", m.Install.Type)\n\t}\n}\n\nfunc validatePinnedArtifactURLs(artifacts []Artifact) error {\n\tfor index, artifact := range artifacts {\n\t\tparsed, errParse := url.Parse(strings.TrimSpace(artifact.URL))\n\t\tif errParse != nil {\n\t\t\treturn fmt.Errorf(\"artifacts[%d]: invalid artifact url\", index)\n\t\t}\n\t\tif parsed.User != nil {\n\t\t\treturn fmt.Errorf(\"artifacts[%d]: pinned artifact url must not contain credentials\", index)\n\t\t}\n\t\tif parsed.RawQuery != \"\" || parsed.Fragment != \"\" {\n\t\t\treturn fmt.Errorf(\"artifacts[%d]: pinned artifact url must not contain query or fragment\", index)","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginstore/manifest.go#L124-L160","documentation":"For github-release installs, Validate() derives a version from the tag via ReleaseVersion() and compares it to the manifest's normalized version field. If they differ, the manifest is internally inconsistent: the pinned tag would install a different version than the manifest declares, so validation fails.","triggerScenarios":"Manifest with version: 1.2.0 but release-tag: v1.3.0; or tag \"release-2024.01\" whose extracted version does not equal the version field; or version \"1.2\" vs tag \"v1.2.0\" when ReleaseVersion yields \"1.2.0\".","commonSituations":"Bumping version in one place but not the other during release automation; renaming tags (v-prefix added/removed) without updating the manifest; cherry-picking a manifest template and only editing one field.","solutions":["Make release-tag and version describe the same release, e.g. version: 1.3.0 with release-tag: v1.3.0","If your tags carry no v-prefix, use release-tag: 1.3.0 — what matters is what ReleaseVersion extracts equals normalizeVersion(version)","Wire CI to render both fields from the same source (git describe / release variable) so they cannot drift"],"exampleFix":"# before\nversion: 1.2.0\nrelease-tag: v1.3.0\n# release-tag \"v1.3.0\" resolves version \"1.3.0\", want \"1.2.0\"\n\n# after\nversion: 1.3.0\nrelease-tag: v1.3.0","handlingStrategy":"validation","validationCode":"rv, err := pluginstore.ReleaseVersion(pluginstore.Release{TagName: m.ReleaseTag})\nif err != nil { return err }\nnorm := m.Version\nif len(norm) > 1 && (norm[0] == 'v' || norm[0] == 'V') { norm = norm[1:] }\nif rv != norm { return fmt.Errorf(\"tag %s does not match version %s\", m.ReleaseTag, m.Version) }","typeGuard":"func tagMatchesVersion(tag, version string) bool { rv, err := pluginstore.ReleaseVersion(pluginstore.Release{TagName: tag}); return err == nil && rv == strings.TrimPrefix(strings.TrimPrefix(version, \"v\"), \"V\") }","tryCatchPattern":"if err := m.Validate(); err != nil && strings.Contains(err.Error(), \"resolves version\") { /* re-derive version from the tag and rewrite manifest */ }","preventionTips":["Single-source both fields from the release tag in CI","Fail the release job when tag and version diverge"],"tags":["pluginstore","manifest","github-release","version-mismatch"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}