{"record":{"id":"fc413d60bfad5889","repo":"AlistGo/alist","slug":"decode-darkibox-result-failed-w","errorCode":null,"errorMessage":"decode darkibox result failed: %w","messagePattern":"decode darkibox result failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/darkibox/util.go","lineNumber":48,"sourceCode":"\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}\n\treturn id\n}\n\n// encodeFolderID prefixes a folder ID so we can distinguish folders from files.\nfunc encodeFolderID(id int64) string {\n\treturn \"d:\" + strconv.FormatInt(id, 10)\n}\n\n// encodeFileID prefixes a file code so we can distinguish files from folders.","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/darkibox/util.go#L30-L66","documentation":"The API call fully succeeded (HTTP 200, provider status 200, non-empty Result) but json.Unmarshal of resp.Result into the caller's target struct failed. The response JSON shape does not match the Go struct being decoded into — schema drift or an unexpected payload type.","triggerScenarios":"Result is an object where an array was expected (or vice versa) for that endpoint; numeric fields returned as strings; null inside a non-pointer field; provider added/renamed nested fields so types no longer line up with e.g. folderCreateResult or uploadServerResult.","commonSituations":"After a provider API update changes response casing or nesting; endpoints reused with the wrong result struct; new endpoints whose schema was guessed during driver development.","solutions":["Log resp.Result (raw JSON) at debug level and compare it against the target struct's json tags; correct the struct","If the provider legitimately varies the shape (object vs array), unmarshal into json.RawMessage first and branch on the first non-space byte","Pin the driver to a known-good provider API version if the platform offers versioned endpoints"],"exampleFix":"// before\nif err := json.Unmarshal(resp.Result, out); err != nil {\n\treturn fmt.Errorf(\"decode darkibox result failed: %w\", err)\n}\n// after — include endpoint and a body snippet\nif err := json.Unmarshal(resp.Result, out); err != nil {\n\treturn fmt.Errorf(\"decode darkibox result failed for %s: %w (body: %.200s)\", endpoint, err, resp.Result)\n}","handlingStrategy":"type-guard","validationCode":"var probe json.RawMessage\nif err := d.callAPI(ctx, endpoint, params, &probe); err == nil {\n\tif !json.Valid(probe) { return errors.New(\"provider returned invalid JSON\") }\n}","typeGuard":"func isDecodeError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"decode darkibox result failed\")\n}","tryCatchPattern":"if isDecodeError(err) {\n\t// schema drift: log raw body, fail fast — retrying identical decode will not help\n\tlog.Errorf(\"schema mismatch: %v\", err)\n\treturn err\n}","preventionTips":["Log raw Result at debug level for postmortems","Pin provider API versions when available","Add contract tests for each endpoint's result struct"],"tags":["darkibox","json","schema-drift","shared-helper"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}