{"record":{"id":"9e1eca2fca57faa0","repo":"flipped-aurora/gin-vue-admin","slug":"url","errorCode":null,"errorMessage":"下载结果缺少 url","messagePattern":"下载结果缺少 url","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/sys_skills.go","lineNumber":434,"sourceCode":"\t}\n\n\tmetaBody, err := io.ReadAll(downloadResp.Body)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"读取下载结果失败: %w\", err)\n\t}\n\n\tvar meta struct {\n\t\tData struct {\n\t\t\tURL string `json:\"url\"`\n\t\t} `json:\"data\"`\n\t}\n\tif err = json.Unmarshal(metaBody, &meta); err != nil {\n\t\treturn fmt.Errorf(\"解析下载结果失败: %w\", err)\n\t}\n\n\trealDownloadURL := strings.TrimSpace(meta.Data.URL)\n\tif realDownloadURL == \"\" {\n\t\treturn errors.New(\"下载结果缺少 url\")\n\t}\n\n\tzipResp, err := http.Get(realDownloadURL)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"下载压缩包失败: %w\", err)\n\t}\n\tdefer zipResp.Body.Close()\n\n\tif zipResp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"下载压缩包失败, HTTP状态码: %d\", zipResp.StatusCode)\n\t}\n\n\ttmpFile, err := os.CreateTemp(\"\", \"gva-skill-*.zip\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"创建临时文件失败: %w\", err)\n\t}\n\ttmpPath := tmpFile.Name()\n\tdefer os.Remove(tmpPath)","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_skills.go#L416-L452","documentation":"DownloadOnlineSkill POSTs to the gin-vue-admin plugin marketplace downloadSkill endpoint and unmarshals {data:{url}}. If the JSON parses but data.url is empty/whitespace, it returns \"下载结果缺少 url\" — the marketplace responded OK but did not provide a real download link (e.g. unknown plugin id/version or upstream change).","triggerScenarios":"Downloading an online skill with an ID/Version that has no published artifact, or when the marketplace API returns a success envelope without a url field (schema change, deleted/unpublished skill).","commonSituations":"Stale plugin ID from an old listing; requesting a version that doesn't exist; marketplace service degradation returning an empty payload; the response shape being changed upstream.","solutions":["Verify the plugin ID and version against the current marketplace listing and retry","Log/inspect the raw response body to see any msg/error field the marketplace returned","Check https://plugin.gin-vue-admin.com availability and whether downloadSkill's response schema changed; update the struct if it did","Fall back to manually packaging the skill locally and importing it"],"exampleFix":"// before\nvar meta struct { Data struct { URL string `json:\"url\"` } `json:\"data\"` }\n// after (surface upstream message too)\nvar meta struct {\n    Data struct { URL string `json:\"url\"` } `json:\"data\"`\n    Msg  string `json:\"msg\"`\n    Code int    `json:\"code\"`\n}\nif err = json.Unmarshal(metaBody, &meta); err != nil { ... }\nif meta.Code != 0 { return fmt.Errorf(\"marketplace error: %s\", meta.Msg) }\nif strings.TrimSpace(meta.Data.URL) == \"\" { return errors.New(\"下载结果缺少 url: \" + meta.Msg) }","handlingStrategy":"retry","validationCode":"// pre-check: confirm id/version exist in the marketplace listing API before download\n// and validate the ID is a known non-empty value client-side\nif req.ID == 0 || req.Version == \"\" { return errors.New(\"请提供有效的插件ID和版本\") }","typeGuard":null,"tryCatchPattern":"if err := svc.DownloadOnlineSkill(ctx, req); err != nil {\n    if err.Error() == \"下载结果缺少 url\" {\n        // surface upstream msg, ask user to verify ID/version, allow retry\n    }\n    return err\n}","preventionTips":["Verify plugin ID/version against the marketplace listing before downloading","Log the raw marketplace response body for diagnosis","Monitor plugin.gin-vue-admin.com API schema changes and pin behavior in tests"],"tags":["network","http","marketplace"],"backgroundTag":"empty-download-url-in-response","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}