{"record":{"id":"113fa27fde0b235e","repo":"Tencent/WeKnora","slug":"task-failed-s","errorCode":null,"errorMessage":"task failed: %s","messagePattern":"task failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go","lineNumber":242,"sourceCode":"\t\t\tlogger.Errorf(context.Background(), \"[PaddleOCR-VL Cloud] poll #%d decode error: %v\", pollCount, err)\n\t\t\tsleepCtx(ctx, paddleOCRVLCloudPollInterval)\n\t\t\tcontinue\n\t\t}\n\n\t\tstate := strings.ToLower(pollResp.Data.State)\n\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\"`","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go#L224-L260","documentation":"The remote PaddleOCR VL parsing task transitioned to state=\"failed\" and pollJob surfaces the provider's ErrorMsg verbatim. The error text after the prefix comes from the cloud service, not from this library, so diagnosis must use the embedded provider message. pollJob returns this to Read, which fails the whole document parse.","triggerScenarios":"pollJob polls a submitted task and pollResp.Data.State == \"failed\"; the provider's pollResp.Data.ErrorMsg is wrapped into \"task failed: %s\" and returned to Read.","commonSituations":"Unsupported or corrupted document uploaded (encrypted PDF, scanned images over size limits); document exceeds provider page/size quota; transient GPU/worker failure on the provider side; invalid API token causing task rejection reported asynchronously.","solutions":["Read the embedded ErrorMsg in the error string and address the provider-specific cause (bad file, quota, unsupported format).","Re-encode/re-upload the document (e.g. re-save the PDF, strip encryption, reduce size/pages).","Retry Read — transient provider worker failures usually succeed on resubmission.","Verify API credentials and account quota with the PaddleOCR cloud service.","If the file is reliably rejected, pre-validate the document locally or fall back to a local OCR parser."],"exampleFix":"// before\nif err := task.SubmitAndPoll(ctx, doc); err != nil {\n    return err // task failed: <provider msg>\n}\n\n// after\nif err := task.SubmitAndPoll(ctx, doc); err != nil {\n    if strings.Contains(err.Error(), \"task failed:\") {\n        return fmt.Errorf(\"cloud OCR rejected document (%v); check file format/size or retry\", err)\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"// pre-validate the document before submitting to the cloud service\nfunc validForCloudOCR(file *os.File) error {\n    st, err := file.Stat()\n    if err != nil { return err }\n    if st.Size() > 50<<20 { return errors.New(\"file exceeds cloud OCR size limit\") }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"err := reader.Read(ctx, file)\nvar providerMsg string\nif err != nil && strings.HasPrefix(err.Error(), \"task failed: \") {\n    providerMsg = strings.TrimPrefix(err.Error(), \"task failed: \")\n    // route providerMsg to logs/alerts and decide retry vs permanent failure\n}","preventionTips":["Pre-check document format, encryption, page count, and size against provider limits.","Surface the embedded provider ErrorMsg to your own logs for actionable diagnosis.","Classify provider messages into retryable vs permanent before auto-retrying.","Verify API credentials and quota in CI/deploy checks."],"tags":["ocr","cloud","remote-task","http-api"],"backgroundTag":"remote-task-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}