{"record":{"id":"44f8d27a5ce2b220","repo":"Tencent/WeKnora","slug":"list-team-repos-w","errorCode":null,"errorMessage":"list team repos: %w","messagePattern":"list team repos: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/datasource/connector/yuque/connector.go","lineNumber":82,"sourceCode":"\t\treturn nil, err\n\t}\n\tcli := newClient(cfg)\n\n\tme, err := cli.GetCurrentUser(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get current user: %w\", err)\n\t}\n\n\trepos := make(map[int64]v2Repo)\n\n\t// Team token: /api/v2/user returns type=\"Group\" — the token represents a team,\n\t// not a personal user. In this case, directly list the team's own repos instead\n\t// of going through the personal-repos + user-groups flow.\n\tif me.Type == \"Group\" {\n\t\tlogger.Infof(ctx, \"[Yuque] detected team token (type=Group, login=%s), listing team repos directly\", me.Login)\n\t\tteamRepos, err := cli.ListGroupRepos(ctx, me.Login)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"list team repos: %w\", err)\n\t\t}\n\t\tfor _, r := range teamRepos {\n\t\t\trepos[r.ID] = r\n\t\t}\n\t} else {\n\t\t// Personal token flow: list user's own repos + repos from joined groups.\n\t\tpersonal, err := cli.ListUserRepos(ctx, me.Login)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"list personal repos: %w\", err)\n\t\t}\n\t\tfor _, r := range personal {\n\t\t\tif _, ok := repos[r.ID]; !ok {\n\t\t\t\trepos[r.ID] = r\n\t\t\t}\n\t\t}\n\n\t\tgroups, err := cli.ListUserGroups(ctx, me.ID)\n\t\tif err != nil {","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/datasource/connector/yuque/connector.go#L64-L100","documentation":"This error wraps a failure from cli.ListGroupRepos while ListResources is listing a Yuque team (Group-type token) knowledge base repos. The connector detected that the token belongs to a Group user, so it lists the group's repos directly; when that upstream API call fails, the underlying error is preserved via %w and prefixed with this message.","triggerScenarios":"A team token whose /me response has Type == \"Group\" is used and the ListGroupRepos API call for that login returns an error (auth failure, network error, API rate limit, or the group login being invalid/deleted).","commonSituations":"Organization tokens issued for a deleted or renamed Yuque org; expired or revoked team token; network restrictions blocking api.yuque.com; the token lacking read scope on the group's repos.","solutions":["Verify the token is valid and belongs to the intended Yuque organization (curl https://api.yuque.com/api/v2/user with the token)","Re-generate the organization token with repo read scope and update the datasource config","Check the wrapped error for 401/403/404: 403 usually means missing scope, 404 means the group login no longer exists","Confirm network egress to api.yuque.com from the connector host"],"exampleFix":"// before\nrepos, err := cli.ListGroupRepos(ctx, me.Login)\nif err != nil {\n    return nil, fmt.Errorf(\"list team repos: %w\", err)\n}\n// after\nif me.Login == \"\" {\n    return nil, fmt.Errorf(\"team token returned empty login; check token validity\")\n}\nrepos, err := cli.ListGroupRepos(ctx, me.Login)\nif err != nil {\n    return nil, fmt.Errorf(\"list team repos (login=%s): %w\", me.Login, err)\n}","handlingStrategy":"try-catch","validationCode":"// Before invoking the datasource, verify the token and team access:\nresp, err := http.NewRequestWithContext(ctx, \"GET\", \"https://api.yuque.com/api/v2/user\", nil)\n// req.Header.Set(\"X-Auth-Token\", token)\n// if err or non-200 -> fix token before configuring the connector","typeGuard":"// Go: check the wrapped cause to branch on auth vs network failures\nvar apiErr *yuque.APIError\nif errors.As(err, &apiErr) && apiErr.StatusCode == 401 {\n    // token invalid: prompt re-authentication\n}","tryCatchPattern":"items, err := ds.ListResources(ctx, cfg)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        return retryWithBackoff(ctx)\n    }\n    return fmt.Errorf(\"yuque team repo listing failed: %w\", err)\n}","preventionTips":["Validate the org token against /api/v2/user during connector setup","Regenerate tokens on a schedule before expiry","Grant org-wide repo read scope when creating the token","Alert on ListResources failures with the wrapped cause logged"],"tags":["yuque","api-error","authentication","connector"],"backgroundTag":"upstream-api-call-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}