Tencent/WeKnora · error
list personal repos: %w
Error message
list personal repos: %w
What it means
This error wraps a failure from cli.ListUserRepos during ListResources' personal-token flow. The /me response indicated a personal user, so the connector fetches the user's own repos; any API-level failure there is wrapped with this prefix while preserving the cause with %w.
Source
Thrown at internal/datasource/connector/yuque/connector.go:91
repos := make(map[int64]v2Repo)
// Team token: /api/v2/user returns type="Group" — the token represents a team,
// not a personal user. In this case, directly list the team's own repos instead
// of going through the personal-repos + user-groups flow.
if me.Type == "Group" {
logger.Infof(ctx, "[Yuque] detected team token (type=Group, login=%s), listing team repos directly", me.Login)
teamRepos, err := cli.ListGroupRepos(ctx, me.Login)
if err != nil {
return nil, fmt.Errorf("list team repos: %w", err)
}
for _, r := range teamRepos {
repos[r.ID] = r
}
} else {
// Personal token flow: list user's own repos + repos from joined groups.
personal, err := cli.ListUserRepos(ctx, me.Login)
if err != nil {
return nil, fmt.Errorf("list personal repos: %w", err)
}
for _, r := range personal {
if _, ok := repos[r.ID]; !ok {
repos[r.ID] = r
}
}
groups, err := cli.ListUserGroups(ctx, me.ID)
if err != nil {
// Yuque returns 404 when the user has not joined any groups (teams),
// instead of an empty list. Treat this as "no groups" and continue
// — personal repos were already fetched above.
logger.Warnf(ctx, "[Yuque] list user groups failed (treating as empty): %v", err)
groups = nil
}
for _, g := range groups {
teamRepos, err := cli.ListGroupRepos(ctx, g.Login)
if err != nil {View on GitHub (pinned to 988cbb0330)
Solutions
- Verify the personal token with curl https://api.yuque.com/api/v2/user and regenerate it if it returns 401
- Ensure the token has read scope for the user's repositories (read_repo or broader)
- Inspect the wrapped error: 429 means back off/poll less frequently; 5xx means retry later or check Yuque status
- Confirm the connector host can reach api.yuque.com (proxy/DNS issues)
Example fix
// before
personal, err := cli.ListUserRepos(ctx, me.Login)
if err != nil {
return nil, fmt.Errorf("list personal repos: %w", err)
}
// after
personal, err := cli.ListUserRepos(ctx, me.Login)
if err != nil {
return nil, fmt.Errorf("list personal repos (user=%s): %w", me.Login, err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Probe the personal token before configuring: // GET https://api.yuque.com/api/v2/user with X-Auth-Token // treat 401 as invalid token, 403 as missing scope
Type guard
var apiErr *yuque.APIError
if errors.As(err, &apiErr) {
switch apiErr.StatusCode {
case 401: // re-auth
case 429: // backoff
}
} Try / catch
items, err := ds.ListResources(ctx, cfg)
if err != nil {
var apiErr *yuque.APIError
if errors.As(err, &apiErr) && apiErr.StatusCode == 429 {
time.Sleep(backoff)
items, err = ds.ListResources(ctx, cfg)
}
if err != nil {
log.Printf("personal repo listing failed: %v", err)
}
} Prevention
- Test the token with a /user API call before saving config
- Keep a documented token rotation process
- Check token scopes include repository read
- Monitor Yuque API rate limits and back off on 429
When it happens
Trigger: A personal Yuque token is configured and ListUserRepos(me.Login) returns an error — invalid/expired token, network failure, rate limiting, or a user whose repos endpoint returns an unexpected error.
Common situations: Personal access token expired or revoked; token created without repo read scope; user account deactivated; yuque API outage or 429 rate limit under heavy polling.
Related errors
- list team repos: %w
- list docs for book %d: %w
- yuque api error: status=%d msg=%s
- yuque api error: status=%d body=%s
- invalid book id %q: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/dea2fc0cf536b149.
Report an issue: GitHub.