Fix: simplify verify go - #17397
Conversation
📝 WalkthroughWalkthroughProvider verification now falls back to remote model listings when local candidates are unavailable. Internal verification also supports ChangesProvider model verification
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (2)
api/apps/services/provider_api_service.pyinternal/service/model_service.go
| 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() |
There was a problem hiding this comment.
🎯 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.
| 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.
| 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 |
There was a problem hiding this comment.
🩺 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: replaceexcept Exception: passwith logged expected-error handling.internal/service/model_service.go#L1005-L1024: log or wraplistErrbefore 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
| if remote_models: | ||
| factory_llms = [ | ||
| { | ||
| "model_type": mt, | ||
| "llm_name": m["name"], | ||
| } | ||
| for m in remote_models | ||
| for mt in m.get("model_types", []) | ||
| ] |
There was a problem hiding this comment.
🎯 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 || trueRepository: 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')
PYRepository: 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 || trueRepository: 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 -nRepository: 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))
PYRepository: 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 Report✅ All modified and coverable lines are covered by tests. 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. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
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 winPreserve remote model-listing errors.
listErris 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 winTrack verification success per model, not only per model type.
The remote fallback can append multiple models of the same type, but the existing
passedTypesoptimization skips later models and then records them asModelVerifyFailbecauseanyPassedremains false. The newdoc_parsecase 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
📒 Files selected for processing (2)
internal/entity/models/mineru.gointernal/service/model_service.go
| 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 |
There was a problem hiding this comment.
🎯 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 -SRepository: 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.goRepository: 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:
- 1: https://github.com/opendatalab/MinerU/blob/05b09412/mineru/cli/fast_api.py
- 2: https://github.com/opendatalab/MinerU/blob/1d154853/mineru/cli/fast_api.py
- 3: https://github.com/opendatalab/MinerU/blob/master/docs/en/usage/quick_usage.md
- 4: Intermittent 404 for /tasks/{task_id} behind multi-replica Kubernetes Service opendatalab/MinerU#5038
- 5: invocation problem opendatalab/MinerU#2952
- 6: https://github.com/hesreallyhim/MinerU-Skill-fork/blob/main/references/api_reference.md
🌐 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:
- 1: Intermittent 404 for /tasks/{task_id} behind multi-replica Kubernetes Service opendatalab/MinerU#5038
- 2: https://github.com/opendatalab/MinerU/blob/a6b6d308/mineru/cli/fast_api.py
- 3: invocation problem opendatalab/MinerU#2961
- 4: 新建的 API token 全部报 A0202 "user authenticate failed"(mineru.net API) opendatalab/MinerU#5133
🌐 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:
- 1: Intermittent 404 for /tasks/{task_id} behind multi-replica Kubernetes Service opendatalab/MinerU#5038
- 2: https://github.com/opendatalab/MinerU/blob/1d154853/mineru/cli/fast_api.py
- 3: https://opendatalab.github.io/MinerU/usage/quick_usage/
- 4: https://github.com/opendatalab/MinerU/blob/master/docs/en/usage/quick_usage.md
- 5: https://github.com/opendatalab/mineru
- 6: https://github.com/hesreallyhim/MinerU-Skill-fork/blob/main/references/api_reference.md
- 7: 新建的 API token 全部报 A0202 "user authenticate failed"(mineru.net API) opendatalab/MinerU#5133
🌐 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:
- 1: Intermittent 404 for /tasks/{task_id} behind multi-replica Kubernetes Service opendatalab/MinerU#5038
- 2: 没有异步任务接口 post /tasks 404 not found opendatalab/MinerU#4680
- 3: invocation problem opendatalab/MinerU#2961
- 4: docs(api): add response models for FastAPI OpenAPI documentation opendatalab/MinerU#5261
🌐 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:
- 1: Intermittent 404 for /tasks/{task_id} behind multi-replica Kubernetes Service opendatalab/MinerU#5038
- 2: https://github.com/opendatalab/MinerU/blob/1d154853/mineru/cli/fast_api.py
- 3: https://opendatalab.github.io/MinerU/usage/quick_usage/
- 4: invocation problem opendatalab/MinerU#2952
- 5: invocation problem opendatalab/MinerU#2961
- 6: authentication_error opendatalab/MinerU#2229
🌐 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:
- 1: 没有异步任务接口 post /tasks 404 not found opendatalab/MinerU#4680
- 2: invocation problem opendatalab/MinerU#2961
- 3: [Bug] MinerU knowledge base preprocessing upload fails (HTTP 404/405 or "File not found") due to plugin implementation not matching official API spec CherryHQ/cherry-studio#13065
- 4: The latest Dify plugin version 0.5.1 cannot call the API applied for from the official website opendatalab/MinerU#4035
- 5: Intermittent 404 for /tasks/{task_id} behind multi-replica Kubernetes Service opendatalab/MinerU#5038
- 6: https://github.com/opendatalab/MinerU-Ecosystem/tree/main/sdk/typescript
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.
…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>
Summary
Fix: