AlistGo/alist · error

ocr error:" + jsoniter.Get(vRes.Body(), "msg").ToString()

Error message

ocr error:" + jsoniter.Get(vRes.Body(), "msg").ToString()

What it means

Raised after the captcha image was forwarded to the configured OCR HTTP service (setting conf.OcrApi, posted as multipart field 'image') and that service answered with a JSON body whose status is not 200. The OCR service's own msg field is appended, e.g. 'ocr error:model not loaded'.

Source

Thrown at drivers/cloudreve/util.go:138

	if needCaptcha {
		var captcha string
		err = d.request(http.MethodGet, "/site/captcha", nil, &captcha)
		if err != nil {
			return err
		}
		if len(captcha) == 0 {
			return errors.New("can not get captcha")
		}
		i := strings.Index(captcha, ",")
		dec := base64.NewDecoder(base64.StdEncoding, strings.NewReader(captcha[i+1:]))
		vRes, err := base.RestyClient.R().SetMultipartField(
			"image", "validateCode.png", "image/png", dec).
			Post(setting.GetStr(conf.OcrApi))
		if err != nil {
			return err
		}
		if jsoniter.Get(vRes.Body(), "status").ToInt() != 200 {
			return errors.New("ocr error:" + jsoniter.Get(vRes.Body(), "msg").ToString())
		}
		captchaCode = jsoniter.Get(vRes.Body(), "result").ToString()
	}
	var resp Resp
	err = d.request(http.MethodPost, loginPath, func(req *resty.Request) {
		req.SetBody(base.Json{
			"username":    d.Addition.Username,
			"Password":    d.Addition.Password,
			"captchaCode": captchaCode,
		})
	}, &resp)
	return err
}

func convertSrc(obj model.Obj) map[string]interface{} {
	m := make(map[string]interface{})
	var dirs []string
	var items []string

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Set the OcrApi setting to a working OCR service (e.g. a deployed ddddocr API: https://github.com/sml2h3/ddddocr) and test it with a manual multipart POST of a PNG.
  2. Check the OCR service logs — its msg field names the exact failure (model missing, decode error).
  3. Disable login captcha on the Cloudrebve side so no OCR is needed.
  4. Ensure the URL in OcrApi is the full endpoint (scheme+host+path) and reachable from the alist/OpenList host.

Example fix

# before: placeholder OCR api
PUT /api/setting/ocr_api  -> ""
# after: working ddddocr service
PUT /api/setting/ocr_api  -> "http://127.0.0.1:9898"
Defensive patterns

Strategy: validation

Validate before calling

// health-check the OCR service before relying on it during login
if setting.GetStr(conf.OcrApi) == "" {
    return errors.New("OcrApi not configured; cannot solve login captcha")
}
if resp, err := http.Get(setting.GetStr(conf.OcrApi) + "/ping"); err != nil || resp.StatusCode != 200 {
    return errors.New("OCR service unreachable")
}

Type guard

func isOcrError(err error) bool {
    return err != nil && strings.HasPrefix(err.Error(), "ocr error:")
}

Try / catch

if err != nil {
    if strings.HasPrefix(err.Error(), "ocr error:") {
        // captcha/OCR path failed: fix OcrApi or disable captcha rather than retrying blindly
        log.Printf("ocr login failed: %s; check conf.OcrApi service", err)
    }
    return err
}

Prevention

When it happens

Trigger: doLogin with captcha enabled: image POSTed to setting.GetStr(conf.OcrApi); response body parsed with jsoniter and status != 200. Happens when the OCR endpoint is misconfigured, down, returns HTML (proxy error page), or the ddddocr-style service fails to recognize/load.

Common situations: conf.OcrApi left pointing at default/placeholder URL; OCR container not running or crashing on the PNG; reverse proxy in front of the OCR service returning 502 HTML so status parses to 0; OCR service version that expects a different field name than 'image'.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/4ba469d57bc2080f. Report an issue: GitHub.