{"record":{"id":"fdedc340de368a96","repo":"github/copilot-sdk","slug":"failed-to-parse-legacy-package-lock-json-w","errorCode":null,"errorMessage":"failed to parse legacy package-lock.json: %w","messagePattern":"failed to parse legacy package-lock\\.json: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/cmd/bundler/main.go","lineNumber":367,"sourceCode":"\turl := fmt.Sprintf(packageLockURLFmt, gitRef)\n\tfmt.Printf(\"Falling back to %s...\\n\", url)\n\n\tresp, err := http.Get(url)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to fetch legacy package-lock.json: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"failed to fetch legacy package-lock.json: %s\", resp.Status)\n\t}\n\n\tvar packageLock struct {\n\t\tPackages map[string]struct {\n\t\t\tVersion string `json:\"version\"`\n\t\t} `json:\"packages\"`\n\t}\n\tif err := json.NewDecoder(resp.Body).Decode(&packageLock); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to parse legacy package-lock.json: %w\", err)\n\t}\n\tpkg, ok := packageLock.Packages[\"node_modules/@github/copilot\"]\n\tif !ok || pkg.Version == \"\" {\n\t\treturn \"\", fmt.Errorf(\"could not find copilotCliVersion in package.json or @github/copilot in package-lock.json\")\n\t}\n\treturn pkg.Version, nil\n}\n\n// isHex returns true if s contains only hexadecimal characters.\nfunc isHex(s string) bool {\n\tfor _, c := range s {\n\t\tif (c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F') {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/cmd/bundler/main.go#L349-L385","documentation":"This error wraps a JSON decoding failure of the downloaded legacy package-lock.json body. The response was received with HTTP 200 but its content could not be parsed into the expected lockfile schema (packages map with version fields). The bundler throws this because it cannot extract the @github/copilot version from malformed content.","triggerScenarios":"json.NewDecoder(resp.Body).Decode fails — the body is empty, HTML (e.g. a proxy or error page returned with 200), truncated, or not valid JSON, while fetching the legacy package-lock.json in fetchLegacyCLIVersionFromRepo.","commonSituations":"Corporate proxies or captive portals returning an HTML login page with status 200; truncated downloads on flaky networks; GitHub serving an error page; a lockfile format change that no longer matches the expected schema.","solutions":["Print/curl the URL and inspect what the body actually contains.","Check for proxy or captive-portal interference returning HTML with a 200 status.","Retry if the download was truncated due to network flakiness.","Verify the lockfile schema still has packages.node_modules/@github/copilot.version.","Validate the JSON with jq to confirm it is well-formed before debugging code."],"exampleFix":"// before\nif err := json.NewDecoder(resp.Body).Decode(&packageLock); err != nil {\n\treturn \"\", fmt.Errorf(\"failed to parse legacy package-lock.json: %w\", err)\n}\n// after\nbody, _ := io.ReadAll(resp.Body)\nif len(bytes.TrimSpace(body)) > 0 && body[0] != '{' {\n\treturn \"\", fmt.Errorf(\"legacy package-lock.json response is not JSON (got %q...)\", body[:32])\n}\nif err := json.Unmarshal(body, &packageLock); err != nil {\n\treturn \"\", fmt.Errorf(\"failed to parse legacy package-lock.json: %w\", err)\n}","handlingStrategy":"validation","validationCode":"body, _ := io.ReadAll(resp.Body)\nif !json.Valid(body) {\n\treturn errors.New(\"response body is not valid JSON\")\n}\nif bytes.Contains(bytes.ToLower(body[:min(len(body),256)]), []byte(\"<html\")) {\n\treturn errors.New(\"got HTML instead of JSON (proxy/portal?)\")\n}","typeGuard":null,"tryCatchPattern":"v, err := fetchLegacyCLIVersionFromRepo(ref)\nvar parseErr error\nif errors.As(err, &parseErr) {\n\t// refetch with a fresh request; check the raw body first\n}","preventionTips":["Validate the response starts with '{' before decoding.","Bypass transparent proxies when fetching raw files.","Retry truncated downloads; use a client with timeouts.","Verify the lockfile schema hasn't changed upstream."],"tags":["json","parsing","http","fallback"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}