open-webui/open-webui · error · HTTPException

MinerU Cloud API response missing batch_id or file_urls

Error message

MinerU Cloud API response missing batch_id or file_urls

What it means

Raised as HTTP 502 when the /file-urls/batch JSON has code == 0 but data lacks batch_id or file_urls (or they are empty). The cloud API claimed success yet omitted the fields required for steps 2-3 (upload and polling), so the response shape does not match what this loader expects.

Source

Thrown at backend/open_webui/retrieval/loaders/mineru.py:281

        except ValueError as e:
            raise HTTPException(
                status.HTTP_502_BAD_GATEWAY,
                detail=f'Invalid JSON response: {e}',
            )

        # Check for API error response
        if result.get('code') != 0:
            raise HTTPException(
                status.HTTP_400_BAD_REQUEST,
                detail=f'MinerU Cloud API error: {result.get("msg", "Unknown error")}',
            )

        data = result.get('data', {})
        batch_id = data.get('batch_id')
        file_urls = data.get('file_urls', [])

        if not batch_id or not file_urls:
            raise HTTPException(
                status.HTTP_502_BAD_GATEWAY,
                detail='MinerU Cloud API response missing batch_id or file_urls',
            )

        upload_url = file_urls[0]
        log.info(f'Received upload URL for batch: {batch_id}')

        return batch_id, upload_url

    def _upload_to_presigned_url(self, upload_url: str) -> None:
        """
        Upload file to presigned URL (no authentication needed).
        """
        log.info(f'Uploading file to presigned URL')

        try:
            with open(self.file_path, 'rb') as f:
                response = requests.put(

View on GitHub (pinned to 01f4282f1f)

Solutions

  1. Log the full response JSON and diff its data keys against batch_id/file_urls
  2. Ensure params does not contain a 'files' key - it would be overridden, but other collisions may leak in
  3. Pin api_url to the API version this loader targets
  4. Check for a 'files' entry mismatch (name/is_ocr fields) in the request

Example fix

// before
params = {'files': [{'name': 'x.pdf'}], 'language': 'en'}  # collides with loader body
loader = MinerULoader(file_path=p, api_mode='cloud', api_key=key, params=params)

// after
params = {'language': 'en'}
loader = MinerULoader(file_path=p, api_mode='cloud', api_key=key, params=params)
Defensive patterns

Strategy: type-guard

Validate before calling

# Prevent the most common trigger: params keys colliding with the request body
assert 'files' not in (params or {}), "params must not contain 'files'"

Type guard

def is_upload_url_response(obj) -> bool:
    if not (isinstance(obj, dict) and obj.get('code') == 0):
        return False
    data = obj.get('data') or {}
    return (
        isinstance(data.get('batch_id'), str)
        and bool(data['batch_id'])
        and isinstance(data.get('file_urls'), list)
        and len(data['file_urls']) > 0
        and isinstance(data['file_urls'][0], str)
    )

Try / catch

try:
    docs = loader.load()
except HTTPException as e:
    if e.status_code == 502 and 'missing batch_id or file_urls' in e.detail:
        log.error('Cloud schema change suspected - capture raw response')
    raise

Prevention

When it happens

Trigger: API version change renaming data fields (e.g. batch_id -> id); an empty file_urls list because the request body's files array was dropped/emptied by a proxy or serialization issue; an A/B schema on the server side.

Common situations: MinerU cloud contract change after an api_url version bump; params containing a 'files' key that shadows the loader's own files field via {**self.params}; middlewares stripping parts of the JSON body.

Related errors


AI-assisted analysis of open-webui/open-webui@01f4282f1f (2026-08-14). Data as JSON: /api/errors/d56db253a19ca322. Report an issue: GitHub.