{"record":{"id":"1f1ac77108d93d03","repo":"AlistGo/alist","slug":"e-message-1f1ac7","errorCode":null,"errorMessage":"e.Message","messagePattern":"e\\.Message","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/teambition/util.go","lineNumber":51,"sourceCode":"\tif d.isInternational() {\n\t\turl = \"https://us.teambition.com\" + pathname\n\t}\n\treq := base.RestyClient.R()\n\treq.SetHeader(\"Cookie\", d.Cookie)\n\tif callback != nil {\n\t\tcallback(req)\n\t}\n\tif resp != nil {\n\t\treq.SetResult(resp)\n\t}\n\tvar e ErrResp\n\treq.SetError(&e)\n\tres, err := req.Execute(method, url)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif e.Name != \"\" {\n\t\treturn nil, errors.New(e.Message)\n\t}\n\treturn res.Body(), nil\n}\n\nfunc (d *Teambition) getFiles(parentId string) ([]model.Obj, error) {\n\tfiles := make([]model.Obj, 0)\n\tpage := 1\n\tfor {\n\t\tvar collections []Collection\n\t\t_, err := d.request(\"/api/collections\", http.MethodGet, func(req *resty.Request) {\n\t\t\treq.SetQueryParams(map[string]string{\n\t\t\t\t\"_parentId\":  parentId,\n\t\t\t\t\"_projectId\": d.ProjectID,\n\t\t\t\t\"order\":      d.OrderBy + d.OrderDirection,\n\t\t\t\t\"count\":      \"50\",\n\t\t\t\t\"page\":       strconv.Itoa(page),\n\t\t\t})\n\t\t}, &collections)","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/teambition/util.go#L33-L69","documentation":"The Teambition request wrapper unmarshals non-2xx/API-error bodies into ErrResp and, when the error has a Name, returns errors.New(e.Message) — surfacing the server's own error text (this lookup key is literally 'e.Message'). Whatever Message the Teambition API put in the error body is what the caller sees, e.g. invalid token, expired session, or object-not-found messages.","triggerScenarios":"Any Teambition API call whose JSON response contains a non-empty Name field in the error structure — expired/invalid cookie or authorization, deleted target collection, quota errors, or rate limiting as reported by the API.","commonSituations":"Login cookie/token expired (most common) — refresh credentials in the storage config; Operating on a collection/task deleted in the Teambition web client concurrently; Account-level issues: 2FA enabled, session revoked, or API region mismatch (teambition.com vs teambition.cn)","solutions":["Re-authenticate: update the storage's cookie/token in alist and re-save to re-run Init","Verify the target object still exists in the Teambition UI and retry","Inspect the full response body (add temporary logging of res.Body()) if the Message is vague, then act on the specific API error","Check for region/endpoint mismatch in the driver config if auth repeatedly fails with cryptic messages"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"body, err := d.request(\"/api/...\", http.MethodGet, cb, &out)\nif err != nil {\n    msg := err.Error()\n    switch {\n    case strings.Contains(msg, \"token\"), strings.Contains(msg, \"unauthorized\"), strings.Contains(msg, \"login\"):\n        // refresh cookie/token in storage config, then retry once\n    case strings.Contains(msg, \"not found\"):\n        // object deleted upstream — drop from cache\n    default:\n        return fmt.Errorf(\"teambition api: %w\", err)\n    }\n}","preventionTips":["Renew Teambition credentials proactively on a schedule rather than after failures","Log response bodies when diagnosing opaque e.Message errors","Avoid concurrent mutations from web UI and driver at once"],"tags":["teambition","api-error","auth","http"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}