{"record":{"id":"05d62b011d4effa6","repo":"Tencent/WeKnora","slug":"docreader-call-timeout-after-s-w","errorCode":null,"errorMessage":"docreader call timeout after %s: %w","messagePattern":"docreader call timeout after (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/knowledge_process.go","lineNumber":3786,"sourceCode":") (*types.ReadResult, error) {\n\ttimeout := 30 * time.Minute\n\tif s.config != nil && s.config.KnowledgeBase != nil && s.config.KnowledgeBase.DocReaderCallTimeout > 0 {\n\t\ttimeout = s.config.KnowledgeBase.DocReaderCallTimeout\n\t}\n\tcallCtx, cancel := context.WithTimeout(ctx, timeout)\n\tdefer cancel()\n\n\tstart := time.Now()\n\tresult, err := reader.Read(callCtx, req)\n\telapsed := time.Since(start)\n\tif err != nil {\n\t\t// Promote DeadlineExceeded into a clearer message; retain underlying\n\t\t// error via %w so errors.Is(callCtx.Err(), context.DeadlineExceeded)\n\t\t// still works for upstream classification.\n\t\tif errors.Is(callCtx.Err(), context.DeadlineExceeded) && !errors.Is(ctx.Err(), context.DeadlineExceeded) {\n\t\t\tlogger.Errorf(ctx, \"[convert] docreader call timed out after %s (limit %s) for %q\",\n\t\t\t\telapsed, timeout, req.FileName)\n\t\t\treturn nil, fmt.Errorf(\"docreader call timeout after %s: %w\", timeout, err)\n\t\t}\n\t\treturn nil, err\n\t}\n\tlogger.Infof(ctx, \"[convert] docreader call ok in %s for %q\", elapsed, req.FileName)\n\treturn result, nil\n}\n\n// isLikelyRateLimitError performs a fuzzy classification of an error as a\n// rate-limit / quota / backpressure failure. We only need a hint — the\n// caller maps to one of two error_codes so the UI can offer \"retry later\"\n// vs. \"fix configuration\" advice. False positives are harmless (the\n// detail is preserved in error_detail anyway).\nfunc isLikelyRateLimitError(err error) bool {\n\tif err == nil {\n\t\treturn false\n\t}\n\tmsg := strings.ToLower(err.Error())\n\tfor _, needle := range []string{\"rate limit\", \"ratelimit\", \"429\", \"too many requests\", \"quota\"} {","sourceCodeStart":3768,"sourceCodeEnd":3804,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/knowledge_process.go#L3768-L3804","documentation":"Thrown by the docreader call wrapper when reader.Read exceeds the configured DocReaderCallTimeout (default 30m). DeadlineExceeded is promoted into this clearer message while %w preserves errors.Is(ctx.Err(), context.DeadlineExceeded) for upstream retry classification — large or slow documents commonly hit it.","triggerScenarios":"Thrown at internal/application/service/knowledge_process.go:3786 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Increase KnowledgeBase.DocReaderCallTimeout in config for large documents","Reduce document size or split very large files before upload","Check docreader service health if typical documents suddenly time out","The task retries via asynq with backoff"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}