{"record":{"id":"69b4b31e28740993","repo":"AlistGo/alist","slug":"failed-to-login-token-is-empty-resp-s","errorCode":null,"errorMessage":"failed to login: token is empty, resp: %s","messagePattern":"failed to login: token is empty, resp: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/ilanzou/util.go","lineNumber":31,"sourceCode":"\t\"github.com/alist-org/alist/v3/pkg/utils\"\n\t\"github.com/foxxorcat/mopan-sdk-go\"\n\t\"github.com/go-resty/resty/v2\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nfunc (d *ILanZou) login() error {\n\tres, err := d.unproved(\"/login\", http.MethodPost, func(req *resty.Request) {\n\t\treq.SetBody(base.Json{\n\t\t\t\"loginName\": d.Username,\n\t\t\t\"loginPwd\":  d.Password,\n\t\t})\n\t})\n\tif err != nil {\n\t\treturn err\n\t}\n\td.Token = utils.Json.Get(res, \"data\", \"appToken\").ToString()\n\tif d.Token == \"\" {\n\t\treturn fmt.Errorf(\"failed to login: token is empty, resp: %s\", res)\n\t}\n\treturn nil\n}\n\nfunc getTimestamp(secret []byte) (int64, string, error) {\n\tts := time.Now().UnixMilli()\n\ttsStr := strconv.FormatInt(ts, 10)\n\tres, err := mopan.AesEncrypt([]byte(tsStr), secret)\n\tif err != nil {\n\t\treturn 0, \"\", err\n\t}\n\treturn ts, hex.EncodeToString(res), nil\n}\n\nfunc (d *ILanZou) request(pathname, method string, callback base.ReqCallback, proved bool, retry ...bool) ([]byte, error) {\n\t_, ts_str, err := getTimestamp(d.conf.secret)\n\tif err != nil {\n\t\treturn nil, err","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/ilanzou/util.go#L13-L49","documentation":"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.","triggerScenarios":"Wrong username/password; account banned or locked; API path prefix (conf.unproved) wrong for the current backend; response envelope changed so data.appToken moved.","commonSituations":"Password rotated but config not updated; credentials containing special characters mangled in the JSON body; provider API version bump; account flagged for programmatic access.","solutions":["Read the embedded resp body — it usually contains the real reason (password error, account locked).","Re-enter username/password in the driver config; verify by logging into the ilanzou web UI with the same credentials.","Regenerate/confirm the API credentials if the provider uses app-specific keys.","Update the driver if the login response contract changed."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// verify credentials are present before driving the client\nif d.Username == \"\" || d.Password == \"\" {\n    return errors.New(\"ilanzou username/password not configured\")\n}","typeGuard":null,"tryCatchPattern":"if err := d.login(); err != nil {\n    if strings.Contains(err.Error(), \"token is empty\") {\n        return errors.New(\"ilanzou credentials rejected — check username/password in storage config\")\n    }\n    return err\n}","preventionTips":["Confirm web-UI login works with the same credentials","Re-enter credentials after password rotation","Avoid special characters that break JSON encoding of the login body"],"tags":["ilanzou","login","credentials","auth"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}