Tencent/WeKnora · error

create request: %w

Error message

create request: %w

What it means

The Yuque client's doRequest builds each HTTP call with http.NewRequestWithContext. If request construction fails (invalid method string, unparsable URL from baseURL+path, or a bad/nil context body), it returns "create request: %w". This happens before any network I/O, so it indicates a programming or configuration error rather than a server problem.

Source

Thrown at internal/datasource/connector/yuque/client.go:64

// client lifetime (not per request) to keep sync logs readable at thousand-doc scale.
func (c *client) doRequest(ctx context.Context, method, path string, result interface{}) error {
	const (
		maxRetries    = 3
		max5xxRetries = 1
		retry5xxDelay = 2 * time.Second
	)
	var lastErr error
	backoff := []time.Duration{2 * time.Second, 4 * time.Second, 8 * time.Second}

	c.logTokenOnce.Do(func() {
		logger.Infof(ctx, "[Yuque] client configured token=%s base=%s", redactToken(c.token), c.baseURL)
	})

	for attempt := 0; attempt <= maxRetries; attempt++ {
		reqURL := c.baseURL + path
		req, err := http.NewRequestWithContext(ctx, method, reqURL, nil)
		if err != nil {
			return fmt.Errorf("create request: %w", err)
		}
		req.Header.Set("X-Auth-Token", c.token)
		req.Header.Set("User-Agent", userAgent)
		req.Header.Set("Content-Type", "application/json; charset=utf-8")

		if attempt == 0 {
			logger.Infof(ctx, "[Yuque] %s %s", method, path)
		} else {
			logger.Infof(ctx, "[Yuque] %s %s (retry %d/%d)", method, path, attempt, maxRetries)
		}

		resp, err := c.httpClient.Do(req)
		if err != nil {
			lastErr = fmt.Errorf("execute request: %w", err)
			if attempt < maxRetries {
				if sErr := sleepCtx(ctx, backoff[attempt]); sErr != nil {
					return sErr
				}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check the YUQUE base URL configuration: it must be an absolute URL with scheme, e.g. https://www.yuque.com/api/v2, with no whitespace.
  2. Trim whitespace and validate the URL with url.Parse before constructing the client.
  3. Verify the method argument is a valid HTTP verb (GET/POST/...).
  4. Ensure the context passed in is a real, non-nil context.

Example fix

// before
baseURL := os.Getenv("YUQUE_BASE_URL") // "yuque.com/api/v2"
// after
u, err := url.Parse(strings.TrimSpace(os.Getenv("YUQUE_BASE_URL")))
if err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("invalid YUQUE_BASE_URL: %q", os.Getenv("YUQUE_BASE_URL"))
}
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(strings.TrimSpace(baseURL + path))
if err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("invalid Yuque URL %q: %v", baseURL+path, err)
}

Type guard

func validURL(s string) bool {
    u, err := url.Parse(s)
    return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
}

Try / catch

err := client.Ping(ctx)
if err != nil && strings.HasPrefix(err.Error(), "create request:") {
    // configuration bug: fix baseURL/method, do not retry
    return err
}

Prevention

When it happens

Trigger: Any of Ping, GetCurrentUser, ListUserGroups, listReposPaginated, ListBookDocs, GetDocDocDetail via doRequest when the method verb is invalid, the baseURL is malformed (bad scheme, spaces, control chars), or path produces an unparseable URL.

Common situations: baseURL configured with a typo like "yuque.com" (no scheme) or a trailing space from an env var; an empty baseURL making the URL unparseable; a custom caller passing a non-standard HTTP method.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/1bef4cf66e16709a. Report an issue: GitHub.