AlistGo/alist · error

r.Msg

Error message

r.Msg

What it means

Returned by Cloudreve driver's request helper when the HTTP call succeeded but the Cloudreve response envelope carries a non-zero business code (r.Code != 0). The server's own message field (r.Msg) is wrapped verbatim, so the text is whatever the Cloudreve instance replied (e.g. 'object not found', 'unauthorized'). It is the catch-all API-level error for every authenticated Cloudreve call that is not a 401-relogin case.

Source

Thrown at drivers/cloudreve/util.go:78

	}
	if !resp.IsSuccess() {
		return errors.New(resp.String())
	}

	if r.Code != 0 {

		// 刷新 cookie
		if r.Code == http.StatusUnauthorized && path != loginPath {
			if d.Username != "" && d.Password != "" {
				err = d.login()
				if err != nil {
					return err
				}
				return d.request(method, path, callback, out)
			}
		}

		return errors.New(r.Msg)
	}
	sess := cookie.GetCookie(resp.Cookies(), "cloudreve-session")
	if sess != nil {
		d.Cookie = sess.Value
	}
	if out != nil && r.Data != nil {
		var marshal []byte
		marshal, err = jsoniter.Marshal(r.Data)
		if err != nil {
			return err
		}
		err = jsoniter.Unmarshal(marshal, out)
		if err != nil {
			return err
		}
	}

	return nil

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Fill in Username and Password in the driver config so an expired session triggers automatic re-login (the code retries once after d.login()).
  2. Re-save the driver storage to force a fresh login and cookie, then retry the failed operation.
  3. Verify the target path/ID still exists and the account has permission for the failing operation on the Cloudreve side.
  4. Check Cloudreve server logs at the same timestamp to see the real reason behind r.Msg.

Example fix

// before: driver addition left Username/Password empty -> expired cookie surfaces raw r.Msg
// after: configure credentials so request() can self-heal
// (in storage addition)
//   username: your-user
//   password: your-pass
// util.go keeps: if r.Code == 401 && d.Username != "" { d.login(); return d.request(...) }
Defensive patterns

Strategy: retry

Validate before calling

// before mounting, verify the session works and credentials allow re-login
if _, err := d.List(ctx, model.Obj(&model.Object{Path: "/"})); err != nil {
    if d.Addition.Username == "" || d.Addition.Password == "" {
        return fmt.Errorf("api error %q and no credentials configured for re-login", err)
    }
}

Type guard

func isCloudreveApiMsg(err error) bool {
    // envelope errors surface verbatim; distinguish from transport errors
    var ue *url.Error
    return err != nil && errors.As(err, &ue) == false && err.Error() != ""
}

Try / catch

if err := d.request(method, path, cb, out); err != nil {
    if strings.Contains(err.Error(), "unauthorized") { // session expired
        if lerr := d.login(); lerr == nil {
            err = d.request(method, path, cb, out) // one retry after re-login
        }
    }
    return err
}

Prevention

When it happens

Trigger: Any driver operation (List/MakeDir/Move/Rename/Copy/Delete/upload callback) where POST/GET to the Cloudreve API answers 200 HTTP but JSON body code != 0, and either the code is not 401 or Username/Password are empty so re-login cannot be attempted. Typical when the session cookie expired and no credentials were configured, the path no longer exists, or the server rejects the operation.

Common situations: Expired cloudreve-session cookie with no username/password filled in the driver addition; wrong root folder ID/path after it was moved or deleted on the server; Cloudrebve upgraded and changed API semantics; read-only or permission-restricted sub-account used for mounting.

Related errors


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