AlistGo/alist · error

failed to login: token is empty, resp: %s

Error message

failed to login: token is empty, resp: %s

What it means

Returned by ILanZou's login() when POST /login succeeded at the HTTP level but the response's data.appToken field is empty. The full raw response body is embedded. It means credentials were rejected or the response shape changed — the server did not hand out a session token.

Source

Thrown at drivers/ilanzou/util.go:31

	"github.com/alist-org/alist/v3/pkg/utils"
	"github.com/foxxorcat/mopan-sdk-go"
	"github.com/go-resty/resty/v2"
	log "github.com/sirupsen/logrus"
)

func (d *ILanZou) login() error {
	res, err := d.unproved("/login", http.MethodPost, func(req *resty.Request) {
		req.SetBody(base.Json{
			"loginName": d.Username,
			"loginPwd":  d.Password,
		})
	})
	if err != nil {
		return err
	}
	d.Token = utils.Json.Get(res, "data", "appToken").ToString()
	if d.Token == "" {
		return fmt.Errorf("failed to login: token is empty, resp: %s", res)
	}
	return nil
}

func getTimestamp(secret []byte) (int64, string, error) {
	ts := time.Now().UnixMilli()
	tsStr := strconv.FormatInt(ts, 10)
	res, err := mopan.AesEncrypt([]byte(tsStr), secret)
	if err != nil {
		return 0, "", err
	}
	return ts, hex.EncodeToString(res), nil
}

func (d *ILanZou) request(pathname, method string, callback base.ReqCallback, proved bool, retry ...bool) ([]byte, error) {
	_, ts_str, err := getTimestamp(d.conf.secret)
	if err != nil {
		return nil, err

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Read the embedded resp body — it usually contains the real reason (password error, account locked).
  2. Re-enter username/password in the driver config; verify by logging into the ilanzou web UI with the same credentials.
  3. Regenerate/confirm the API credentials if the provider uses app-specific keys.
  4. Update the driver if the login response contract changed.
Defensive patterns

Strategy: validation

Validate before calling

// verify credentials are present before driving the client
if d.Username == "" || d.Password == "" {
    return errors.New("ilanzou username/password not configured")
}

Try / catch

if err := d.login(); err != nil {
    if strings.Contains(err.Error(), "token is empty") {
        return errors.New("ilanzou credentials rejected — check username/password in storage config")
    }
    return err
}

Prevention

When it happens

Trigger: Wrong username/password; account banned or locked; API path prefix (conf.unproved) wrong for the current backend; response envelope changed so data.appToken moved.

Common situations: Password rotated but config not updated; credentials containing special characters mangled in the JSON body; provider API version bump; account flagged for programmatic access.

Related errors


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