{"record":{"id":"561ef6f00768ac92","repo":"AlistGo/alist","slug":"ocr-error-empty-result","errorCode":null,"errorMessage":"ocr error: empty result","messagePattern":"ocr error: empty result","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/cloudreve_v4/util.go","lineNumber":161,"sourceCode":"\t\t}\n\t\tif !strings.HasPrefix(captcha.Image, \"data:image/png;base64,\") {\n\t\t\treturn errors.New(\"can not get captcha\")\n\t\t}\n\t\tloginBody[\"ticket\"] = captcha.Ticket\n\t\ti := strings.Index(captcha.Image, \",\")\n\t\tdec := base64.NewDecoder(base64.StdEncoding, strings.NewReader(captcha.Image[i+1:]))\n\t\tvRes, err := base.RestyClient.R().SetMultipartField(\n\t\t\t\"image\", \"validateCode.png\", \"image/png\", dec).\n\t\t\tPost(setting.GetStr(conf.OcrApi))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif jsoniter.Get(vRes.Body(), \"status\").ToInt() != 200 {\n\t\t\treturn errors.New(\"ocr error:\" + jsoniter.Get(vRes.Body(), \"msg\").ToString())\n\t\t}\n\t\tcaptchaCode := jsoniter.Get(vRes.Body(), \"result\").ToString()\n\t\tif captchaCode == \"\" {\n\t\t\treturn errors.New(\"ocr error: empty result\")\n\t\t}\n\t\tloginBody[\"captcha\"] = captchaCode\n\t}\n\tvar token TokenResponse\n\terr = d.request(http.MethodPost, \"/session/token\", func(req *resty.Request) {\n\t\treq.SetBody(loginBody)\n\t}, &token)\n\tif err != nil {\n\t\treturn err\n\t}\n\td.AccessToken, d.RefreshToken = token.Token.AccessToken, token.Token.RefreshToken\n\top.MustSaveDriverStorage(d)\n\treturn nil\n}\n\nfunc (d *CloudreveV4) refreshToken() error {\n\tvar token Token\n\tif token.RefreshToken == \"\" {","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/cloudreve_v4/util.go#L143-L179","documentation":"CloudreveV4 login: the OCR service answered status 200 but its result field was an empty string, so there is no captcha code to submit. This isolates the failure to the OCR stage (recognition produced nothing) rather than transport or service errors.","triggerScenarios":"jsoniter.Get(vRes.Body(), \"result\").ToString() == \"\" after a 200 OCR response. Happens when the OCR model returns an empty prediction for the image, the response shape differs (result nested elsewhere), or the image bytes sent were corrupt.","commonSituations":"ddddocr returning empty for hard captcha images; service returning {\"status\":200} with data under a different key; truncated base64 decode of the captcha image; wrong captcha type yielding an image OCR cannot read.","solutions":["Manually POST the exact captcha PNG to the OCR service and inspect the full JSON — confirm the result key and value.","Retry login (the driver already retries up to 5 times on 'CAPTCHA not match', but empty OCR aborts; a retry may get a fresh, more readable captcha).","Switch to a better OCR service/model for this captcha style.","Disable captcha on the Cloudrebve V4 site to avoid the OCR path."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"captchaCode := jsoniter.Get(vRes.Body(), \"result\").ToString()\nif captchaCode == \"\" { return errors.New(\"ocr error: empty result\") }","typeGuard":null,"tryCatchPattern":"if err := d.doLogin(true); err != nil {\n    if err.Error() == \"ocr error: empty result\" {\n        time.Sleep(time.Second)\n        return d.doLogin(true) // fresh captcha image may OCR cleanly\n    }\n    return err\n}","preventionTips":["Retry with a fresh captcha when OCR yields empty","Use an OCR model adequate for the captcha style","Verify the OCR response schema (flat 'result' key) when swapping services"],"tags":["cloudreve-v4","ocr","captcha","go"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}