{"record":{"id":"7ff4775970dbae59","repo":"GopeedLab/gopeed","slug":"extension-title-is-required","errorCode":null,"errorMessage":"extension title is required","messagePattern":"extension title is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/download/extension.go","lineNumber":441,"sourceCode":"\tScripts    []*Script   `json:\"scripts\"`\n\tSettings   []*Setting  `json:\"settings\"`\n\t// Disabled if true, this extension will be ignored\n\tDisabled bool `json:\"disabled\"`\n\n\tDevMode bool `json:\"devMode\"`\n\t// DevPath is the local path of extension source code\n\tDevPath string `json:\"devPath\"`\n\n\tCreatedAt time.Time `json:\"createdAt\"`\n\tUpdatedAt time.Time `json:\"updatedAt\"`\n}\n\nfunc (e *Extension) validate() error {\n\tif e.Name == \"\" {\n\t\treturn fmt.Errorf(\"extension name is required\")\n\t}\n\tif e.Title == \"\" {\n\t\treturn fmt.Errorf(\"extension title is required\")\n\t}\n\tif e.Version == \"\" {\n\t\treturn fmt.Errorf(\"extension version is required\")\n\t}\n\treturn nil\n}\n\nfunc (e *Extension) buildIdentity() string {\n\tif e.Author == \"\" {\n\t\treturn e.Name\n\t}\n\treturn e.Author + \"@\" + e.Name\n}\n\nfunc (e *Extension) buildInstallUrl() string {\n\tif e.Repository == nil || e.Repository.Url == \"\" {\n\t\treturn \"\"\n\t}","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/GopeedLab/gopeed/blob/7b7327ffb30816273a74b142cccc0bc10c5a4c67/pkg/download/extension.go#L423-L459","documentation":"Extension.validate() requires a non-empty title in manifest.json. The title is the human-readable display name shown in the extensions UI, so an empty one fails install even when name and version are present. It is checked second, after name.","triggerScenarios":"manifest.json with a \"name\" but missing or empty \"title\"; title key misspelled (\"label\", \"Title\") so the field stays zero after unmarshal.","commonSituations":"Minimal manifests written quickly for testing; converting another format's manifest and dropping the display-name field; templates where title defaults to a placeholder that was cleared.","solutions":["Add a non-empty \"title\" to manifest.json","Double-check exact key spelling and top-level placement","Reinstall the extension after fixing the manifest"],"exampleFix":"// before (manifest.json)\n{ \"name\": \"my-extension\", \"version\": \"1.0.0\" }\n// after\n{ \"name\": \"my-extension\", \"title\": \"My Extension\", \"version\": \"1.0.0\" }","handlingStrategy":"validation","validationCode":"// Go: pre-validate manifest title\nvar m map[string]any\n_ = json.Unmarshal(raw, &m)\nif s, _ := m[\"title\"].(string); strings.TrimSpace(s) == \"\" {\n    return fmt.Errorf(\"manifest.json: 'title' is required\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Fill title (display name) in addition to name (slug) in the template","Check exact key spelling — 'title', top-level","Re-validate after renaming keys when porting manifests from other formats"],"tags":["extension","manifest","validation","install"],"backgroundTag":null,"analyzedSha":"7b7327ffb30816273a74b142cccc0bc10c5a4c67","analyzedAt":"2026-08-16T02:51:03.250Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}