Skip to content

Fix: simplify verify go - #17397

Merged
wangq8 merged 3 commits into
infiniflow:mainfrom
Lynn-Inf:fix/simplify-verify-go
Jul 27, 2026
Merged

Fix: simplify verify go#17397
wangq8 merged 3 commits into
infiniflow:mainfrom
Lynn-Inf:fix/simplify-verify-go

Conversation

@Lynn-Inf

@Lynn-Inf Lynn-Inf commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix:

  • Same impelement as python, verify remote model when model_list in argument is [].
  • Verify minerU.net model

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 27, 2026
@Lynn-Inf Lynn-Inf added the ci Continue Integration label Jul 27, 2026
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Provider verification now falls back to remote model listings when local candidates are unavailable. Internal verification also supports doc_parse, while MinerU validates authenticated connectivity against its document parsing endpoint.

Changes

Provider model verification

Layer / File(s) Summary
Remote model fallback
api/apps/services/provider_api_service.py, internal/service/model_service.go
API and internal verification retrieve remote models when earlier candidates are empty, infer or map model metadata, and retain the existing empty-model errors when no candidates are found.
Document parsing connection verification
internal/service/model_service.go, internal/entity/models/mineru.go
doc_parse verification calls CheckConnection; MinerU validates configuration, sends an authenticated timed request, and handles authentication failures explicitly.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: 🐞 bug

Suggested reviewers: wangq8

Poem

I hopped through models, near and far,
Found remote names beneath each star.
MinerU checked the parseway bright,
With bearer token, timeout right—
Verification now sees the light!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and refers to the Go verification logic changed in this PR, though it is a bit broad.
Description check ✅ Passed The description includes the required Summary section and clearly states the main changes to remote model verification and MinerU support.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@api/apps/services/provider_api_service.py`:
- Around line 672-685: Preserve remote discovery failures by logging the
provider name and caught error without API-key details, while narrowing the
exception handling around ModelMeta provider listing to expected
provider/listing errors and avoiding a bare pass; update
api/apps/services/provider_api_service.py:672-685 accordingly. In
internal/service/model_service.go:1005-1024, log or wrap listErr with provider
context before returning the fallback error, while retaining the existing
fallback behavior.
- Around line 671-674: Update the verification model-client construction in the
surrounding provider flow to use the resolved model_base_url rather than the
original base_url, including the paths around the model clients at lines 716 and
734. Preserve the existing fallback resolution from factory_info so both
discovery and subsequent verification use the same URL.
- Around line 675-683: Update the remote model handling in the factory LLM
payload construction to reuse the same normalization rules as the Go
verification path: skip invalid entries, ignore models with empty names, and
infer model types from the model name when model_types is missing or empty.
Replace the direct comprehension around factory_llms with the normalized remote
model set so valid models are preserved consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2791b98f-1d41-413c-8aab-8a27f5bf9b2b

📥 Commits

Reviewing files that changed from the base of the PR and between 53afc32 and 4c1d873.

📒 Files selected for processing (2)
  • api/apps/services/provider_api_service.py
  • internal/service/model_service.go

Comment on lines +671 to +674
model_base_url = base_url or factory_info[0].get("url", "")
try:
if provider_name in ModelMeta:
remote_models = await ModelMeta[provider_name](api_key, model_base_url).get_model_list()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Propagate the resolved model_base_url into verification.

model_base_url is used only for remote discovery, while subsequent model clients receive base_url (for example, at Line 716 and Line 734). If the caller omits base_url and the factory URL is used, discovery can succeed but verification is sent without that resolved URL.

Suggested fix
             model_base_url = base_url or factory_info[0].get("url", "")
+            base_url = model_base_url
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
model_base_url = base_url or factory_info[0].get("url", "")
try:
if provider_name in ModelMeta:
remote_models = await ModelMeta[provider_name](api_key, model_base_url).get_model_list()
model_base_url = base_url or factory_info[0].get("url", "")
base_url = model_base_url
try:
if provider_name in ModelMeta:
remote_models = await ModelMeta[provider_name](api_key, model_base_url).get_model_list()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/apps/services/provider_api_service.py` around lines 671 - 674, Update the
verification model-client construction in the surrounding provider flow to use
the resolved model_base_url rather than the original base_url, including the
paths around the model clients at lines 716 and 734. Preserve the existing
fallback resolution from factory_info so both discovery and subsequent
verification use the same URL.

Comment on lines +672 to +685
try:
if provider_name in ModelMeta:
remote_models = await ModelMeta[provider_name](api_key, model_base_url).get_model_list()
if remote_models:
factory_llms = [
{
"model_type": mt,
"llm_name": m["name"],
}
for m in remote_models
for mt in m.get("model_types", [])
]
except Exception:
pass

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Preserve remote discovery failures for diagnosis.

Both fallbacks discard the underlying provider error and surface only “no models found,” hiding authentication, network, and response failures. Log the provider and error without exposing the API key; narrow the Python catch to expected provider/listing errors where possible.

As per coding guidelines, new Python flows must add logging; Ruff also flags the broad exception catch and pass.

  • api/apps/services/provider_api_service.py#L672-L685: replace except Exception: pass with logged expected-error handling.
  • internal/service/model_service.go#L1005-L1024: log or wrap listErr before returning the fallback error.
🧰 Tools
🪛 Ruff (0.15.21)

[error] 684-685: try-except-pass detected, consider logging the exception

(S110)


[warning] 684-684: Do not catch blind exception: Exception

(BLE001)

📍 Affects 2 files
  • api/apps/services/provider_api_service.py#L672-L685 (this comment)
  • internal/service/model_service.go#L1005-L1024
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/apps/services/provider_api_service.py` around lines 672 - 685, Preserve
remote discovery failures by logging the provider name and caught error without
API-key details, while narrowing the exception handling around ModelMeta
provider listing to expected provider/listing errors and avoiding a bare pass;
update api/apps/services/provider_api_service.py:672-685 accordingly. In
internal/service/model_service.go:1005-1024, log or wrap listErr with provider
context before returning the fallback error, while retaining the existing
fallback behavior.

Sources: Coding guidelines, Linters/SAST tools

Comment on lines +675 to +683
if remote_models:
factory_llms = [
{
"model_type": mt,
"llm_name": m["name"],
}
for m in remote_models
for mt in m.get("model_types", [])
]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate file =="
fd -a 'provider_api_service\.py$' . || true

echo "== Inspect targeted section =="
if [ -f api/apps/services/provider_api_service.py ]; then
  wc -l api/apps/services/provider_api_service.py
  sed -n '630,710p' api/apps/services/provider_api_service.py | cat -n
fi

echo "== Search Go fallback references =="
rg -n --hidden --glob '!*.pyc' 'model_types|llm_name|name|fallback|remote' . | head -200 || true

Repository: infiniflow/ragflow

Length of output: 16828


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect focused Go provider API section =="
rg -n --hidden --glob '!*.pyc' 'Lines 1007|model_type|model_types|remote' . | head -300 || true

python3 - <<'PY'
from pathlib import Path
p = Path('api/apps/services/provider_api_service.py')
if p.exists():
    text = p.read_text()
    start = text.find('if remote_models:')
    end = text.find('\n                ', start) if start >=0 else -1
    print('Python snippet start', start)
    print(text[start:start+500] if start>=0 else 'not found')
PY

Repository: infiniflow/ragflow

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Repo roots =="
git rev-parse --show-toplevel
git ls-files | sed -n '1,120p'

echo "== Look for Go source files =="
git ls-files | grep -E '\.(go|mod|sum)$' | head -80 || true

echo "== Search targeted provider API function names =="
rg -n --hidden --glob '!*.pyc' 'provider_api_service|GetProvider|VerifyProvider|verify_provider|_factory_model_types|remote_models|model_types' api apps . --ignore-case | head -200 || true

echo "== Python function names =="
rg -n --iglob 'api/apps/services/provider_api_service.py' 'def .*provider|VerifyProvider|VerifyLLMApiKey|model_list|remote_models|model_types|factory_fn|_factory_model_types' api/apps/services/provider_api_service.py || true

Repository: infiniflow/ragflow

Length of output: 27726


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Go provider API files =="
rg -n --hidden --glob '!*.pyc' --glob '*.go' 'VerifyProvider|verifyProvider|Provider models|model_types|GetModelList|get_model_list|factory' internal --glob '!*test.go' | head -250 || true

echo "== Locate provider model.go files =="
git ls-files | grep -E 'internal/.*model.*\.go$|internal/.*/provider|api/.*/provider' | head -200 || true

echo "== Exact search remote/fallback section =="
rg -n --hidden --glob '*.go' 'model_types|ModelMeta|modelList|Name:|name' internal/web internal/api internal/controller internal/svc 2>/dev/null | head -300 || true

echo "== Inspect targeted Python normalization helper =="
sed -n '1,55p' api/apps/services/provider_api_service.py | cat -n
sed -n '660,715p' api/apps/services/provider_api_service.py | cat -n

Repository: infiniflow/ragflow

Length of output: 36062


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Go model_service provider verification section =="
sed -n '964,1045p' internal/service/model_service.go | cat -n
echo
echo "== Go model_service list provider endpoint fallback section =="
sed -n '3490,3560p' internal/service/model_service.go | cat -n
echo
echo "== Deterministic Python behavior for sparse remote_models =="
python3 - <<'PY'
remote_models = [
    {"name": "valid-name", "model_types": ["chat"]},
    {"name": "", "model_types": ["embedding"]},
    {"name": "named-only"},
    {"model_types": ["chat"]},
]
factory_llms = [
    {"model_type": mt, "llm_name": m["name"]}
    for m in remote_models
    for mt in m.get("model_types", [])
]
print(factory_llms)
print("kept", len(factory_llms), "dropped", len(remote_models) - len(factory_llms))
PY

Repository: infiniflow/ragflow

Length of output: 7118


Reuse Go’s remote model normalization before building verification payloads.

This list comprehension drops invalid remote entries and still fails for entries missing name or model_types, unlike the Go verify path that skips empty names and infers types from the model name when ModelTypes is empty. Build the factory LLMs from the same normalized/skipped/inferred model set so remote models are not discarded only in Python.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/apps/services/provider_api_service.py` around lines 675 - 683, Update the
remote model handling in the factory LLM payload construction to reuse the same
normalization rules as the Go verification path: skip invalid entries, ignore
models with empty names, and infer model types from the model name when
model_types is missing or empty. Replace the direct comprehension around
factory_llms with the normalized remote model set so valid models are preserved
consistently.

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.65%. Comparing base (cd9db94) to head (68cb863).
⚠️ Report is 42 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #17397   +/-   ##
=======================================
  Coverage   90.65%   90.65%           
=======================================
  Files          10       10           
  Lines         717      717           
  Branches      118      118           
=======================================
  Hits          650      650           
  Misses         39       39           
  Partials       28       28           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
internal/service/model_service.go (2)

1005-1024: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Preserve remote model-listing errors.

listErr is ignored, so authentication, timeout, or provider API failures are reported only as the misleading "no models found for provider". Return or wrap the listing error when no usable remote models are available.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/service/model_service.go` around lines 1005 - 1024, Update the
remote model listing flow around driver.ListModels and modelsToVerify so that
when no usable remote models are available, it returns or wraps listErr if one
occurred instead of always reporting “no models found for provider.” Preserve
the existing no-model error when listing succeeds but yields no usable models.

1003-1020: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Track verification success per model, not only per model type.

The remote fallback can append multiple models of the same type, but the existing passedTypes optimization skips later models and then records them as ModelVerifyFail because anyPassed remains false. The new doc_parse case is affected too. This can persist false failures for valid remote models; key the cache by (modelName, modelType) or propagate cached success into the current model result.

Also applies to: 1061-1062

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/service/model_service.go` around lines 1003 - 1020, The model
verification flow around the remote fallback and passedTypes handling must track
success per model and model type, not only per model type. Update the
verification cache/result logic near the remote model construction and the
additional verification branch so a previously successful (modelName, modelType)
pair is reused for that exact model, while later models sharing a type are still
verified or receive their cached success instead of being recorded as
ModelVerifyFail.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/entity/models/mineru.go`:
- Around line 127-134: Update CheckConnection to accept only HTTP 200 and the
intentionally documented task-not-found status; return an error for every other
status, including 400, 429, 500, and 503. Preserve the existing authentication
error handling while ensuring unexpected responses cannot be treated as a
successful connection.

---

Outside diff comments:
In `@internal/service/model_service.go`:
- Around line 1005-1024: Update the remote model listing flow around
driver.ListModels and modelsToVerify so that when no usable remote models are
available, it returns or wraps listErr if one occurred instead of always
reporting “no models found for provider.” Preserve the existing no-model error
when listing succeeds but yields no usable models.
- Around line 1003-1020: The model verification flow around the remote fallback
and passedTypes handling must track success per model and model type, not only
per model type. Update the verification cache/result logic near the remote model
construction and the additional verification branch so a previously successful
(modelName, modelType) pair is reused for that exact model, while later models
sharing a type are still verified or receive their cached success instead of
being recorded as ModelVerifyFail.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 81da069d-771f-46e7-b718-ac91517b6ef9

📥 Commits

Reviewing files that changed from the base of the PR and between 4c1d873 and 68cb863.

📒 Files selected for processing (2)
  • internal/entity/models/mineru.go
  • internal/service/model_service.go

Comment on lines +127 to +134
if resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {
body, _ := io.ReadAll(resp.Body)
return fmt.Errorf("authentication failed (HTTP %d): %s", resp.StatusCode, string(body))
}

// Non-auth errors (e.g. 404) indicate the server is reachable and
// credentials are valid.
return nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg 'internal/entity/models/mineru\.go|model_service\.go|build\.sh|internal/development\.md' || true

echo "== mineru.go outline =="
ast-grep outline internal/entity/models/mineru.go || true

echo "== relevant mineru.go lines =="
sed -n '1,220p' internal/entity/models/mineru.go

echo "== occurrences of CheckConnection/doc_parse/MinerU =="
rg -n "CheckConnection|doc_parse|NewMinerUModel|MinerU|mineru" internal -S

Repository: infiniflow/ragflow

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== model_service CheckConnection integration =="
sed -n '550,640p' internal/service/model_service.go
sed -n '1048,1072p' internal/service/model_service.go
sed -n '3170,3190p' internal/service/model_service.go

echo "== MinerU task polling behavior =="
sed -n '50,110p' internal/parser/parser/pdf_parser_mineru.go

echo "== MinerU local CheckConnection =="
sed -n '90,120p' internal/entity/models/mineru_local.go

Repository: infiniflow/ragflow

Length of output: 7812


🌐 Web query:

MinerU api v4 extract task task_id status 404 credentials valid

💡 Result:

A 404 status code when accessing a MinerU API task_id (e.g., /tasks/{task_id} or /extract/task/{task_id}) generally indicates that the requested task cannot be found [1][2]. Despite having valid credentials, this error is typically caused by one of the following scenarios: 1. Task Retention and Cleanup: MinerU APIs often implement automatic cleanup of task states and results after a certain duration [3]. Once a task is cleaned up, the task_id no longer exists, and subsequent status or result requests will return a 404 [3]. You can check your instance's configuration for variables like MINERU_API_TASK_RETENTION_SECONDS to understand how long tasks are persisted [3]. 2. Multi-Process or Load-Balanced Deployments: In multi-worker or Kubernetes deployments, task state is often stored in the local memory of the specific mineru-api process that accepted the initial request [4]. If a subsequent status request is routed to a different worker pod or process that does not hold the state for that task_id, it will return a 404 [4]. The official recommendation to resolve this is to use mineru-router, which manages task-to-worker affinity by tracking which worker processed a given task_id and routing subsequent queries appropriately [4]. 3. Expired or Invalid Session: While a 401 Unauthorized error specifically indicates a credential issue, a 404 can occasionally occur if the API gateway or backend infrastructure loses context for the request or if the request is routed to an incorrect endpoint path [5]. If you are using the public MinerU API (https://mineru.net/api/v4), ensure your request is hitting the correct endpoint path [6]. If you are self-hosting, verify your architecture for sticky routing or persistence issues [4]. You can verify the health of your service via the /health endpoint to ensure the API is functioning correctly [3].

Citations:


🌐 Web query:

site:github.com/opendatalab/MinerU extract/task task_id 404 valid credentials

💡 Result:

A 404 error when querying an extract/task endpoint with a task_id in MinerU typically indicates that the requested task cannot be found [1][2]. This occurs due to how task state is managed and accessed within the system [1]. Key reasons and solutions for this error include: 1. Multi-Replica Deployment Inconsistency (Most Common) In a distributed environment (e.g., Kubernetes) with multiple replicas, task states are stored in the local process memory of the specific worker that accepted the initial request [1]. If a subsequent status check request (GET /tasks/{task_id}) is routed to a different replica, that instance will not have the task in its memory, resulting in a 404 error [1]. Solution: Use the documented mineru-router component [1]. This router tracks task-to-worker affinity, ensuring that all follow-up requests for a specific task_id are routed back to the exact worker instance that initiated the task [1]. 2. Endpoint Mismatch Users sometimes attempt to use endpoints meant for different purposes [3]. For example, some endpoints (like certain /extract/task implementations in different API versions) are reserved for specific prompt-based tasks and will return errors or 404s if used for PDF extraction requests, which should instead use the /file_parse endpoint [3]. 3. Authentication Issues While a 404 indicates a missing resource, users have reported receiving authentication-related errors (e.g., 401 "user authenticate failed") when using tokens with the v4 API [4]. Ensure your Bearer token is valid and that your account has the necessary permissions (e.g., active subscription or correct role) to access the requested API version [4]. 4. Expired or Invalid Task ID If the task has been processed and removed from the system's memory (or if the task_id was constructed incorrectly), the server will return a 404 [1][2]. Verify that the task_id exactly matches the one returned by the initial POST request [1]. To troubleshoot, verify your architecture's load balancing settings, ensure you are using the correct endpoint for your specific operation (e.g., /file_parse vs /extract/task), and confirm that your API token is correctly authorized [1][4][3].

Citations:


🌐 Web query:

MinerU api extract/task/{task_id} returns 404 invalid credentials

💡 Result:

A 404 error when accessing the MinerU extract/task/{task_id} or tasks/{task_id} endpoint does not typically indicate an "invalid credential" error; it specifically means the system cannot locate the task associated with the provided ID [1][2]. There are two primary scenarios that cause this 404 error: 1. Task Retention Expiration: MinerU by default retains task state and output files for only 24 hours [3][4]. After this retention period, the task is automatically cleaned up, and any subsequent attempts to query the task_id will return a 404 [3][4]. 2. Multi-Process/Load-Balanced Deployment Issues: If you are self-hosting MinerU and running multiple API replicas behind a load balancer (e.g., in Kubernetes), you may encounter intermittent 404s [1]. This occurs because task state is stored in the local process memory of the specific API instance that accepted the request [1][3]. If a status query is routed to a different replica that did not process the original task, it will not have the task in its memory and will return a 404 [1]. To resolve this in multi-instance environments, you must use the mineru-router component, which maintains task-to-worker affinity [1][5]. Note on Authentication: If you are receiving an "invalid credentials" or "user authenticate failed" message (often associated with error code A0202 or HTTP 401), this is a distinct issue from a 404 [6][7]. Ensure your Bearer token is valid, has not expired, and is correctly included in the Authorization header [6][7]. If you are experiencing 401 errors even with a newly generated token, verify if your account requires additional activation or role upgrades on the official MinerU platform [7]. Top results: [1], [7], [3], [4]

Citations:


🌐 Web query:

MinerU api extract/task/{task_id} returns 404 valid credentials

💡 Result:

A 404 error when querying MinerU's GET /tasks/{task_id} or GET /tasks/{task_id}/result endpoints typically arises from one of three scenarios, even when credentials appear valid: 1. Improper Load Balancing in Multi-Replica Deployments In self-hosted environments using multiple replicas (e.g., in Kubernetes), task states are stored in the local process memory of the specific container instance that initiated the task [1]. If a status check request is routed to a different replica that does not have that task_id in its local memory, it will return a 404 "Task not found" error [1]. * Solution: Use mineru-router to maintain task-to-worker affinity, ensuring that follow-up requests for a specific task_id are routed back to the instance that owns the task [1]. 2. Using Incompatible APIs (SaaS vs. Open Source) The MinerU cloud SaaS API and the self-hosted open-source version use different API structures [2]. Users sometimes encounter 404 errors when attempting to use SaaS-specific endpoints on a locally deployed instance that does not support them [2]. * Solution: Verify the available endpoints by visiting your local instance's Swagger documentation (e.g., http://localhost:8000/docs) [2][3]. For local deployments, ensure you are using the correct endpoints (typically /file_parse for synchronous processing) [2][3]. 3. Running the Incorrect Service If you have started a service like mineru-sglang-server (intended for VLM tasks) rather than the mineru-api FastAPI server, the document parsing and task endpoints will be missing or unreachable [3]. * Solution: Stop the current service and ensure you are running the FastAPI server, for example: python3 -m mineru.cli.fast_api [3]. In all cases, you can confirm the registered routes and their expected behavior by checking your instance's /openapi.json or /docs page to ensure the task_id path exists and is correctly implemented [4][2].

Citations:


🌐 Web query:

github.com/opendatalab/MinerU fast_api.py task_id 404 valid credentials

💡 Result:

A 404 error when accessing a task_id via MinerU's fast_api.py typically indicates that the requested task cannot be located by the API instance receiving the request [1][2][3]. This is rarely related to "valid credentials" but rather to how tasks are managed and routed [1][4]. Common causes and solutions include: 1. Task Retention and Cleanup: By default, MinerU retains task status and output for 24 hours [3]. Once a task is cleaned up, any attempt to access its status or result will return a 404 [3]. You can adjust this behavior by modifying the environment variables MINERU_API_TASK_RETENTION_SECONDS and MINERU_API_TASK_CLEANUP_INTERVAL_SECONDS [3]. 2. Distributed Deployment (In-Memory Storage): Task state is stored in the local process memory of the mineru-api instance where it was created [1][3]. If you are running multiple API replicas (e.g., in Kubernetes) behind a load balancer, subsequent requests for a task_id may be routed to a different instance that has no record of that task, resulting in a 404 [1]. - Solution: Use the mineru-router component, which is designed to track task-to-worker affinity and route requests to the correct instance [1]. 3. Incorrect API/Server Type: If you are encountering 404s for specific endpoints like /file_parse, ensure you are running the FastAPI server (mineru-api) and not a different service, such as an sglang server, which may not have those routes registered [5]. Regarding credentials: If you are using the public MinerU cloud service, a 401 Unauthorized error (not 404) would indicate invalid or missing authentication headers [4][6]. If you are running a local or private Docker deployment, API keys are generally not required unless you have explicitly configured them for external service communication [4]. Ensure your requests are hitting the correct endpoint and that your service container is running the intended mineru-api component [5][4].

Citations:


🌐 Web query:

"mineru.net" "api/v4" "task" "404" "credentials"

💡 Result:

A 404 error when accessing mineru.net/api/v4/task or related endpoints typically stems from one of the following causes: 1. Version Mismatch (Local vs. Cloud API): If you are attempting to use the /tasks (asynchronous) endpoint on a local deployment of MinerU, you will likely receive a 404 error [1]. The asynchronous /tasks interface is primarily designed for the official cloud SaaS (mineru.net) and may not exist in your local installation, which often only supports the synchronous /file_parse endpoint [1]. You can verify your local available endpoints by checking http://<your-host>:<port>/docs [1][2]. 2. Plugin or SDK Incompatibility: If you are using a third-party application (such as Cherry Studio or Dify) and encounter a 404 error at /api/v4/, it is often because the application's plugin implementation is using outdated, hardcoded, or incorrect API paths that do not align with the current MinerU official API specification [3][4]. Updates to these plugins are required to support the latest /api/v4 structure [3]. 3. Load Balancing Issues (In-Process Storage): In multi-replica Kubernetes environments, a 404 error for /tasks/{task_id} can occur if the task was submitted to one worker but the status check is routed to another [5]. This happens because MinerU's default task state is stored in the local memory of the worker process, not in a shared database [5]. To resolve this, you must use a router (like mineru-router) to ensure sticky session routing for task-related requests [5]. 4. Missing Credentials: When using the MinerU SDK or API, ensure that your authentication token is correctly configured [6][4]. If an API key is required but missing or improperly passed in the request header, some API gateways may return 404 errors as a security measure to prevent unauthorized discovery of resources [4]. Ensure your token is set in your environment variables (e.g., MINERU_TOKEN) or passed directly to the client constructor [6][4]. To troubleshoot, verify that you are hitting the correct base URL for your specific service (e.g., https://mineru.net/api/v4 for cloud or your local IP for self-hosted) and that your deployment supports the specific endpoints you are calling [6][3].

Citations:


Reject unexpected HTTP statuses instead of treating them as authenticated success.

CheckConnection currently accepts any non-401/403 response, so bad client failures (400/429) and server failures (500/503) make doc_parse verification pass. Only accept 200 and intentionally documented task-not-found responses; return errors for all other failures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/entity/models/mineru.go` around lines 127 - 134, Update
CheckConnection to accept only HTTP 200 and the intentionally documented
task-not-found status; return an error for every other status, including 400,
429, 500, and 503. Preserve the existing authentication error handling while
ensuring unexpected responses cannot be treated as a successful connection.

@Lynn-Inf
Lynn-Inf requested a review from wangq8 July 27, 2026 05:54
@wangq8
wangq8 merged commit 9bec8d1 into infiniflow:main Jul 27, 2026
6 checks passed
ondery added a commit to ondery/ragflow that referenced this pull request Jul 28, 2026
…er type fail

Two remaining verify-path fixes after infiniflow#17158 (api_base -> base_url rename)
and infiniflow#17364/infiniflow#17397 (empty-catalog remote model discovery) landed on main:

- useVerifyProvider now accepts a modelInfoRef carrying the models selected
  in the List-models picker (not registered as form fields) and folds them
  into the verify payload, so local/compatible providers no longer verify
  against an empty model_info.
- _record_model_verify_failure records FAIL without overwriting a prior
  SUCCESS for the same llm_name. model_info is unrolled into one
  factory_llms entry per capability type, so a later type failure must not
  erase an earlier successful capability result.
- Wrap Embedding/Chat model construction in try/except so an init failure
  is recorded as a per-model FAIL instead of aborting the whole verify.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Continue Integration size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants