{"record":{"id":"e900e4ed7af4d92b","repo":"twpayne/chezmoi","slug":"s-s-s","errorCode":null,"errorMessage":"%s: %s: %s","messagePattern":"%s: %s: %s","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/chezmoi/sourcestate.go","lineNumber":1884,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\tresp, err := chezmoilog.LogHTTPRequest(ctx, s.logger, s.httpClient, req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tvar data []byte\n\tif options == nil || options.ReadHTTPResponse == nil {\n\t\tdata, err = io.ReadAll(resp.Body)\n\t} else {\n\t\tdata, err = options.ReadHTTPResponse(urlStr, resp)\n\t}\n\t_ = resp.Body.Close()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif resp.StatusCode < http.StatusOK || http.StatusMultipleChoices <= resp.StatusCode {\n\t\treturn nil, fmt.Errorf(\"%s: %s: %s\", externalRelPath, urlStr, resp.Status)\n\t}\n\n\tif err := MkdirAll(s.baseSystem, cachedDataAbsPath.Dir(), 0o700); err != nil {\n\t\treturn nil, err\n\t}\n\tif err := s.baseSystem.WriteFile(cachedDataAbsPath, data, 0o600); err != nil {\n\t\treturn nil, err\n\t}\n\tif err := s.baseSystem.Chtimes(cachedDataAbsPath, now, now); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn data, nil\n}\n\n// newCreateTargetStateEntryFunc returns a targetStateEntryFunc that returns a\n// file with the value of sourceContentsFunc if the file does not already exist,\n// or returns the actual file's contents unchanged if the file already exists.","sourceCodeStart":1866,"sourceCodeEnd":1902,"githubUrl":"https://github.com/twpayne/chezmoi/blob/f901167e4685db90da56d6a2a19df642cb3e0247/internal/chezmoi/sourcestate.go#L1866-L1902","documentation":"Returned by SourceState.getExternalDataRaw when the HTTP response status is outside 200-299 (and not a multiple-choice redirect). It wraps the URL and the server's status text so the developer sees which remote request failed and why.","triggerScenarios":"chezmoi downloads an external asset (archive/file) and the server replies 404, 403, 500, etc.; resp.StatusCode < 200 || >= 300 triggers this before caching the data.","commonSituations":"External URL points at a moved/renamed GitHub release asset (404); private repo asset fetched without auth (403); rate-limited or misconfigured mirror (5xx); tag changed upstream.","solutions":["Open the url from the error in a browser/curl and fix it in .chezmoiexternal (e.g. update to the new release tag)","If authentication is required, configure credentials or use a token-authenticated URL","Add a fallback second url entry so chezmoi can retry with a mirror"],"exampleFix":"// before\nurl = \"https://github.com/user/repo/archive/v1.2.3.tar.gz\"\n// after\nurl = \"https://github.com/user/repo/archive/v1.2.4.tar.gz\"","handlingStrategy":"retry","validationCode":"// check URL reachability before pinning it\nresp, err := http.Head(url); if err != nil || resp.StatusCode != 200 { /* pick another url */ }","typeGuard":null,"tryCatchPattern":"// wrap apply and retry once on non-2xx\nif err := chezmoiApply(); err != nil {\n    if strings.Contains(err.Error(), \": 4\") || strings.Contains(err.Error(), \": 5\") {\n        refreshExternalURL(); retry()\n    }\n}","preventionTips":["Pin external URLs to stable release tags, not moving targets","Provide a fallback mirror URL in the external entry","Monitor upstream repos for renamed/moved release assets"],"tags":["network","http","external"],"backgroundTag":"http-non-2xx-status","analyzedSha":"f901167e4685db90da56d6a2a19df642cb3e0247","analyzedAt":"2026-09-01T18:16:41.508Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T01:17:15.007Z"}