Tencent/WeKnora · error

create request: %w

Error message

create request: %w

What it means

submitJob constructs the outbound POST with http.NewRequestWithContext using c.baseURL. If the URL is invalid/unparseable (http.NewRequestWithContext error) or the SSRF-safe client's Do call fails (DNS failure, connection refused, TLS error, timeout, context cancelled), the error is wrapped as 'create request' or surfaces from this submission step. The upload never reached the PaddleOCR-VL cloud API.

Source

Thrown at internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go:140

		fileName = "document." + ext
	}

	var body bytes.Buffer
	writer := multipart.NewWriter(&body)
	_ = writer.WriteField("model", c.model)
	_ = writer.WriteField("optionalPayload", string(optional))
	part, err := writer.CreateFormFile("file", filepath.Base(fileName))
	if err != nil {
		return "", fmt.Errorf("create form file: %w", err)
	}
	if _, err := part.Write(content); err != nil {
		return "", fmt.Errorf("write file content: %w", err)
	}
	writer.Close()

	httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL, &body)
	if err != nil {
		return "", fmt.Errorf("create request: %w", err)
	}
	httpReq.Header.Set("Authorization", "bearer "+c.token)
	httpReq.Header.Set("Content-Type", writer.FormDataContentType())

	client := utils.NewSSRFSafeHTTPClient(utils.SSRFSafeHTTPClientConfig{Timeout: 60 * time.Second, MaxRedirects: 5})
	resp, err := client.Do(httpReq)
	if err != nil {
		return "", fmt.Errorf("HTTP request: %w", err)
	}
	defer resp.Body.Close()

	respBody, _ := io.ReadAll(resp.Body)
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("API status %d: %s", resp.StatusCode, string(respBody))
	}

	var result paddleOCRVLCloudSubmitResponse
	if err := json.Unmarshal(respBody, &result); err != nil {

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Check the wrapped cause: URL parse error vs. transport error (connection refused / DNS / TLS / timeout)
  2. Verify the configured base URL is absolute and correct, including the https:// scheme
  3. Test connectivity to the endpoint from the deployment environment (curl / egress rules)
  4. If behind a proxy, configure proxy settings for the HTTP client
  5. Retry on transient timeouts; increase the 60s timeout for large uploads

Example fix

// before
baseURL := "api.paddleocr.example.com/v1/jobs" // missing scheme -> parse error
// after
baseURL := "https://api.paddleocr.example.com/v1/jobs"
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(c.baseURL)
if err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("invalid PaddleOCR-VL baseURL %q: %w", c.baseURL, err)
}
if err := validateMinerUOutboundURL(c.baseURL); err != nil { return err } // or equivalent SSRF check

Type guard

func isRequestCreationError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "create request")
}

Try / catch

out, err := reader.Read(ctx, req)
if isRequestCreationError(err) {
    if errors.Is(err, context.DeadlineExceeded) || isNetTransient(err) {
        out, err = retryWithBackoff(3, reader.Read, ctx, req)
    }
    if err != nil { return err }
}

Prevention

When it happens

Trigger: Read -> submitJob: c.baseURL is malformed (missing scheme, bad characters) causing NewRequestWithContext to fail; or client.Do errors on network unreachable, DNS failure, connection refused, TLS handshake failure, 60s timeout, or ctx cancellation.

Common situations: Missing/mistyped PADDLEOCR base URL env var (e.g. forgot https://); egress firewall blocking the cloud endpoint; DNS misconfiguration in the cluster; corporate proxy required but not configured; cloud endpoint temporarily down.

Related errors


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