{"record":{"id":"f5753904d790c549","repo":"router-for-me/CLIProxyAPI","slug":"missing-required-field-version","errorCode":null,"errorMessage":"missing required field version","messagePattern":"missing required field version","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginstore/manifest.go","lineNumber":105,"sourceCode":"\t\tHomepage:    strings.TrimSpace(m.Homepage),\n\t\tLicense:     strings.TrimSpace(m.License),\n\t\tTags:        append([]string(nil), m.Tags...),\n\t\tInstall:     NormalizeInstallPlan(m.Install),\n\t}\n}\n\nfunc (m Manifest) InstallType() string {\n\tinstallType := strings.ToLower(strings.TrimSpace(m.Install.Type))\n\tif installType == \"\" {\n\t\treturn InstallTypeGitHubRelease\n\t}\n\treturn installType\n}\n\nfunc (m Manifest) Validate() error {\n\tversion := strings.TrimSpace(m.Version)\n\tif version == \"\" {\n\t\treturn fmt.Errorf(\"missing required field version\")\n\t}\n\tif !validPluginVersion(normalizeVersion(version)) {\n\t\treturn fmt.Errorf(\"invalid plugin version %q\", m.Version)\n\t}\n\tswitch m.InstallType() {\n\tcase InstallTypeDirect:\n\t\tif m.SchemaVersion != 0 && m.SchemaVersion != SchemaVersionV2 {\n\t\t\treturn fmt.Errorf(\"unsupported schema-version %d\", m.SchemaVersion)\n\t\t}\n\t\tif errID := validateManifestPluginID(m.ID); errID != nil {\n\t\t\treturn errID\n\t\t}\n\t\tplan := NormalizeInstallPlan(m.Install)\n\t\tplan.Type = InstallTypeDirect\n\t\tif len(plan.Artifacts) > 0 {\n\t\t\tif errValidate := ValidateInstallPlan(plan); errValidate != nil {\n\t\t\t\treturn errValidate\n\t\t\t}","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginstore/manifest.go#L87-L123","documentation":"Returned by Manifest.Validate (manifest.go:102-106) as the first validation step: the Version field is empty after trimming. Every manifest — whether installed via InstallManifest, generated by ManifestFromPlugin, or validated standalone — must carry an explicit version because it feeds the versioned library filename (<id>-v<version><ext>) and version equality checks during install.","triggerScenarios":"Calling InstallManifest or Manifest.Validate on a Manifest whose Version was never set: a hand-written plugin manifest YAML omitting 'version:', a manifest built via struct literal without Version, or a github-release manifest whose version was expected to be inferred (it is not — ManifestFromRelease fills it from the release tag).","commonSituations":"Authoring a plugin manifest and forgetting the version field; deserialization mismatch (JSON uses version_version snake_case 'version_' vs yaml 'version' — populating the wrong tag silently leaves it empty); assuming Validate fills defaults (it only rejects).","solutions":["Set Manifest.Version to a valid semver-style value (e.g. 1.2.3) matching the release tag for github-release manifests","If generating from a release, use ManifestFromRelease which derives Version via ReleaseVersion","Check the field your deserializer actually populated — the yaml tag is 'version', the json tag is 'version_'"],"exampleFix":"# before (manifest yaml)\nid: myplugin\ninstall:\n  type: github-release\nrelease-tag: v1.2.3\n# after\nid: myplugin\nversion: 1.2.3\ninstall:\n  type: github-release\nrelease-tag: v1.2.3","handlingStrategy":"validation","validationCode":"func manifestHasVersion(m pluginstore.Manifest) error {\n    if strings.TrimSpace(m.Version) == \"\" {\n        return errors.New(\"manifest missing version\")\n    }\n    return nil\n}","typeGuard":"func manifestVersionPresent(m pluginstore.Manifest) bool {\n    return strings.TrimSpace(m.Version) != \"\"\n}","tryCatchPattern":"if err := manifest.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"missing required field version\") {\n        // populate Version (from release tag or build metadata) and re-validate\n    }\n}","preventionTips":["Template new manifests with version pre-filled","Use ManifestFromRelease so Version is derived from the release automatically","Mind the struct tags: yaml 'version' vs json 'version_' — populate through the tag your loader uses"],"tags":["pluginstore","manifest","validation"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}