{"record":{"id":"b3903e7e7de86a9a","repo":"AlistGo/alist","slug":"darkibox-http-error-d","errorCode":null,"errorMessage":"darkibox http error: %d","messagePattern":"darkibox http error: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/darkibox/util.go","lineNumber":39,"sourceCode":"\t}\n\tfor k, v := range params {\n\t\tif strings.TrimSpace(v) == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tquery[k] = v\n\t}\n\n\tvar resp apiResponse\n\tr, err := base.RestyClient.R().\n\t\tSetContext(ctx).\n\t\tSetQueryParams(query).\n\t\tSetResult(&resp).\n\t\tGet(apiBase + endpoint)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif r.StatusCode() != http.StatusOK {\n\t\treturn fmt.Errorf(\"darkibox http error: %d\", r.StatusCode())\n\t}\n\tif resp.Status != 200 {\n\t\treturn fmt.Errorf(\"darkibox api error: status=%d msg=%s\", resp.Status, resp.Msg)\n\t}\n\tif out == nil || len(resp.Result) == 0 || string(resp.Result) == \"null\" {\n\t\treturn nil\n\t}\n\tif err := json.Unmarshal(resp.Result, out); err != nil {\n\t\treturn fmt.Errorf(\"decode darkibox result failed: %w\", err)\n\t}\n\treturn nil\n}\n\n// fldIDStr converts a folder ID (which may be the root \"0\") to a string suitable for API params.\nfunc fldIDStr(id string) string {\n\tif id == \"\" {\n\t\treturn \"0\"\n\t}","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/darkibox/util.go#L21-L57","documentation":"The central callAPI helper in the Darkibox driver rejects any non-200 HTTP status from the API endpoint. This error wraps every darkibox operation (list, mkdir, move, upload-server, etc.) when the transport succeeded but the server answered with an error status. Note it fires before the provider's own status/msg check, so no API-level detail is available.","triggerScenarios":"Any GET to apiBase+endpoint returning 401/403 (auth), 404 (wrong apiBase or endpoint renamed), 429 (rate limit), or 5xx (provider outage). Cloudflare in front of the API returning 403/503 HTML pages is a frequent cause.","commonSituations":"Wrong apiBase configured (provider moved domains); API key disabled; aggressive polling triggering 429; CDN/WAF challenges because the key is sent as a query parameter.","solutions":["curl the exact URL with the same query params to see the raw status and body; identify whether it is auth (401/403), routing (404), rate limit (429), or outage (5xx)","404 → update apiBase to the provider's current domain; 401/403 → renew the API key; 429 → reduce request frequency / add caching","5xx → wait and retry; check the provider's status page"],"exampleFix":"// before\nif r.StatusCode() != http.StatusOK {\n\treturn fmt.Errorf(\"darkibox http error: %d\", r.StatusCode())\n}\n// after — include endpoint and body snippet for diagnosis\nif r.StatusCode() != http.StatusOK {\n\treturn fmt.Errorf(\"darkibox http error: %d on %s: %.200s\", r.StatusCode(), endpoint, r.Body())\n}","handlingStrategy":"retry","validationCode":"if _, err := url.Parse(apiBase); err != nil {\n\treturn errors.New(\"invalid darkibox apiBase\")\n}\nif d.APIKey == \"\" {\n\treturn errors.New(\"API key required\")\n}","typeGuard":null,"tryCatchPattern":"if m := regexp.MustCompile(`darkibox http error: (\\d+)`).FindStringSubmatch(err.Error()); m != nil {\n\tcode, _ := strconv.Atoi(m[1])\n\tif code == 429 || code >= 500 { return backoffRetry() }\n\tif code == 401 || code == 403 { return reconfigure() }\n}","preventionTips":["Cache list results to avoid 429s from aggressive polling","Keep apiBase aligned with provider docs","Handle 5xx with backoff, never tight loops"],"tags":["darkibox","http-status","api-error","shared-helper"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}