{"record":{"id":"b4af4e290fc0d285","repo":"larksuite/cli","slug":"npm-registry-empty-version","errorCode":null,"errorMessage":"npm registry: empty version","messagePattern":"npm registry: empty version","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/update/update.go","lineNumber":223,"sourceCode":"\t\treturn \"\", err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"npm registry: HTTP %d\", resp.StatusCode)\n\t}\n\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, maxBody))\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tvar result npmLatestResponse\n\tif err := json.Unmarshal(body, &result); err != nil {\n\t\treturn \"\", err\n\t}\n\tif result.Version == \"\" {\n\t\treturn \"\", fmt.Errorf(\"npm registry: empty version\")\n\t}\n\treturn result.Version, nil\n}\n\n// --- semver helpers ---\n\n// IsNewer returns true if version a should be considered an update over b.\n//\n// When both parse as semver, standard comparison applies.\n// When b cannot be parsed (e.g. bare commit hash \"9b933f1\"), any valid a\n// is considered newer — an unparseable local version is assumed outdated.\n// When a cannot be parsed, returns false (can't confirm it's newer).\nfunc IsNewer(a, b string) bool {\n\tap := parseVersionDetail(a)\n\tbp := parseVersionDetail(b)\n\tif ap == nil {\n\t\treturn false // can't confirm remote is newer\n\t}","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/update/update.go#L205-L241","documentation":"After a successful HTTP 200 fetch from the npm registry, the JSON body is unmarshaled into npmLatestResponse. If the dist-tags.latest version field is missing or empty, this error is thrown rather than proceeding with a blank version. It guards against corrupted or schema-changed registry responses being treated as a valid latest version.","triggerScenarios":"npm registry returns HTTP 200 with a JSON body whose 'version' (dist-tags.latest) field is absent or empty string, during RefreshCache or FetchLatest.","commonSituations":"Registry-side schema changes, intermediate proxies/CDNs returning a valid-JSON page that is not the package metadata, cached error payloads, or mirror/registry misconfiguration (e.g. custom npm registry pointing at the wrong path).","solutions":["Retry the update check; the response may have been transiently malformed.","Verify any configured npm registry/mirror is the correct package metadata endpoint.","Clear caches/interceptors that might serve stale JSON instead of the registry response.","If persistent, report the issue; the CLI falls back to using the current version."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// pre-validate expected registry response shape when fetching manually\nvar probe struct {\n    Version string `json:\"version\"`\n}\nif json.Unmarshal(body, &probe) == nil && probe.Version == \"\" {\n    // treat as invalid registry response; use fallback\n}","typeGuard":null,"tryCatchPattern":"ver, err := updater.FetchLatest(ctx)\nif err != nil {\n    log.Printf(\"latest-version lookup failed, assuming current: %v\", err)\n    ver = currentVersion\n}","preventionTips":["Avoid custom npm mirrors/registries for the CLI's update channel unless they mirror the exact metadata endpoint.","Cache the last known-good version and fall back to it on parse failures.","Alert on repeated empty-version responses — usually a proxy or schema issue.","Pin the update channel to the official registry when behind intercepting proxies."],"tags":["json","update-check","npm-registry","response-parsing"],"backgroundTag":"unexpected-response-schema","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}