Tencent/WeKnora · error

task timed out after %d polls

Error message

task timed out after %d polls

What it means

pollJob has a fixed poll budget; if the remote task never reaches state "done" or "failed" before the loop is exhausted, it returns this timeout error. The remote task may still be running or stuck. The number of polls is included to aid debugging of polling interval/budget tuning.

Source

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

		if pollCount == 1 || pollCount%6 == 0 || state == "done" || state == "failed" {
			logger.Infof(context.Background(), "[PaddleOCR-VL Cloud] poll #%d: state=%s pages=%d/%d",
				pollCount, state, pollResp.Data.ExtractProgress.ExtractedPages, pollResp.Data.ExtractProgress.TotalPages)
		}

		switch state {
		case "done":
			if pollResp.Data.ResultURL.JSONURL == "" {
				return "", fmt.Errorf("state=done but no jsonUrl")
			}
			return pollResp.Data.ResultURL.JSONURL, nil
		case "failed":
			return "", fmt.Errorf("task failed: %s", pollResp.Data.ErrorMsg)
		}

		sleepCtx(ctx, paddleOCRVLCloudPollInterval)
	}

	return "", fmt.Errorf("task timed out after %d polls", pollCount)
}

// --- result parsing ---

type paddleOCRVLCloudResultLine struct {
	Result struct {
		LayoutParsingResults []struct {
			Markdown struct {
				Text   string            `json:"text"`
				Images map[string]string `json:"images"`
			} `json:"markdown"`
		} `json:"layoutParsingResults"`
	} `json:"result"`
}

func (c *PaddleOCRVLCloudReader) fetchResults(jsonlURL string) (string, map[string]string, error) {
	if err := utils.ValidateURLForSSRF(jsonlURL); err != nil {
		return "", nil, fmt.Errorf("jsonl URL blocked by SSRF check: %v", err)

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Retry Read — if the task eventually completes server-side, resubmission often succeeds.
  2. Increase the poll budget: raise the poll-count limit or the paddleOCRVLCloudPollInterval constant to cover large documents.
  3. Submit smaller documents (split the PDF) to stay within the polling window.
  4. Check the provider status page/queue depth for ongoing incidents.
  5. If the provider supports it, adopt a deadline-based poll (context with generous timeout) instead of a fixed poll count.

Example fix

// before (fixed budget)
for i := 0; i < maxPolls; i++ { pollOnce() }
return "", fmt.Errorf("task timed out after %d polls", pollCount)

// after (deadline-based)
ctx, cancel := context.WithTimeout(ctx, 15*time.Minute)
defer cancel()
for {
    done, url, err := pollOnce(ctx)
    if done || err != nil { return url, err }
    select {
    case <-ctx.Done():
        return "", fmt.Errorf("task timed out after %d polls", pollCount)
    case <-time.After(pollInterval):
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// estimate required polling budget from document size before calling Read
pages := estimatePages(pdfBytes)
requiredTimeout := time.Duration(pages) * 5 * time.Second
ctx, cancel := context.WithTimeout(context.Background(), requiredTimeout)
defer cancel()

Try / catch

url, err := reader.Read(ctx, file)
if err != nil && strings.Contains(err.Error(), "task timed out") {
    // back off and retry once with a larger budget
    time.Sleep(5 * time.Second)
    url, err = reader.Read(ctx, file)
}
if err != nil { return err }

Prevention

When it happens

Trigger: pollJob loops paddleOCRVLCloudPollInterval between polls and reaches the loop limit while pollResp.Data.State is still "processing"/"pending"; invoked from Read on a large or slow document.

Common situations: Very large PDFs or long documents that exceed the provider's typical processing time; provider degradation/queue backlog; poll interval or poll-count constant set too low after a version change; network throttling making polls slow so the wall-clock budget lapses.

Understand the failure class

Related errors


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