{"record":{"id":"fd4db2c4fd5d469f","repo":"Tencent/WeKnora","slug":"task-timed-out-after-d-polls","errorCode":null,"errorMessage":"task timed out after %d polls","messagePattern":"task timed out after (.+?) polls","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go","lineNumber":248,"sourceCode":"\t\tif pollCount == 1 || pollCount%6 == 0 || state == \"done\" || state == \"failed\" {\n\t\t\tlogger.Infof(context.Background(), \"[PaddleOCR-VL Cloud] poll #%d: state=%s pages=%d/%d\",\n\t\t\t\tpollCount, state, pollResp.Data.ExtractProgress.ExtractedPages, pollResp.Data.ExtractProgress.TotalPages)\n\t\t}\n\n\t\tswitch state {\n\t\tcase \"done\":\n\t\t\tif pollResp.Data.ResultURL.JSONURL == \"\" {\n\t\t\t\treturn \"\", fmt.Errorf(\"state=done but no jsonUrl\")\n\t\t\t}\n\t\t\treturn pollResp.Data.ResultURL.JSONURL, nil\n\t\tcase \"failed\":\n\t\t\treturn \"\", fmt.Errorf(\"task failed: %s\", pollResp.Data.ErrorMsg)\n\t\t}\n\n\t\tsleepCtx(ctx, paddleOCRVLCloudPollInterval)\n\t}\n\n\treturn \"\", fmt.Errorf(\"task timed out after %d polls\", pollCount)\n}\n\n// --- result parsing ---\n\ntype paddleOCRVLCloudResultLine struct {\n\tResult struct {\n\t\tLayoutParsingResults []struct {\n\t\t\tMarkdown struct {\n\t\t\t\tText   string            `json:\"text\"`\n\t\t\t\tImages map[string]string `json:\"images\"`\n\t\t\t} `json:\"markdown\"`\n\t\t} `json:\"layoutParsingResults\"`\n\t} `json:\"result\"`\n}\n\nfunc (c *PaddleOCRVLCloudReader) fetchResults(jsonlURL string) (string, map[string]string, error) {\n\tif err := utils.ValidateURLForSSRF(jsonlURL); err != nil {\n\t\treturn \"\", nil, fmt.Errorf(\"jsonl URL blocked by SSRF check: %v\", err)","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go#L230-L266","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Retry Read — if the task eventually completes server-side, resubmission often succeeds.","Increase the poll budget: raise the poll-count limit or the paddleOCRVLCloudPollInterval constant to cover large documents.","Submit smaller documents (split the PDF) to stay within the polling window.","Check the provider status page/queue depth for ongoing incidents.","If the provider supports it, adopt a deadline-based poll (context with generous timeout) instead of a fixed poll count."],"exampleFix":"// before (fixed budget)\nfor i := 0; i < maxPolls; i++ { pollOnce() }\nreturn \"\", fmt.Errorf(\"task timed out after %d polls\", pollCount)\n\n// after (deadline-based)\nctx, cancel := context.WithTimeout(ctx, 15*time.Minute)\ndefer cancel()\nfor {\n    done, url, err := pollOnce(ctx)\n    if done || err != nil { return url, err }\n    select {\n    case <-ctx.Done():\n        return \"\", fmt.Errorf(\"task timed out after %d polls\", pollCount)\n    case <-time.After(pollInterval):\n    }\n}","handlingStrategy":"retry","validationCode":"// estimate required polling budget from document size before calling Read\npages := estimatePages(pdfBytes)\nrequiredTimeout := time.Duration(pages) * 5 * time.Second\nctx, cancel := context.WithTimeout(context.Background(), requiredTimeout)\ndefer cancel()","typeGuard":null,"tryCatchPattern":"url, err := reader.Read(ctx, file)\nif err != nil && strings.Contains(err.Error(), \"task timed out\") {\n    // back off and retry once with a larger budget\n    time.Sleep(5 * time.Second)\n    url, err = reader.Read(ctx, file)\n}\nif err != nil { return err }","preventionTips":["Size the poll budget to document size; large PDFs need more polls.","Prefer deadline-based polling (context timeout) over a fixed poll count.","Monitor provider status/queue latency to tune the poll interval.","Split very large documents before submission."],"tags":["timeout","polling","ocr","cloud"],"backgroundTag":"polling-timeout","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}