HKUDS/Vibe-Trading · error · HTTPException

format must be html or pdf

Error message

format must be html or pdf

What it means

The shadow report endpoint only serves HTML and PDF formats; any other `format` value is rejected with 400 before file lookup.

Source

Thrown at agent/src/api/uploads_routes.py:105

        host = _sys.modules.get("api_server") or _sys.modules.get("agent.api_server")
        return host.MAX_UPLOAD_SIZE if host else MAX_UPLOAD_SIZE

    def _host_chunk_size() -> int:
        import sys as _sys

        host = _sys.modules.get("api_server") or _sys.modules.get("agent.api_server")
        return host._UPLOAD_CHUNK_SIZE if host else _UPLOAD_CHUNK_SIZE

    @app.get("/shadow-reports/{shadow_id}", dependencies=[Depends(require_auth)])
    async def get_shadow_report(shadow_id: str, format: str = "html"):
        """Serve a rendered Shadow Account report.

        Reports live under ``~/.vibe-trading/shadow_reports/<shadow_id>.{html,pdf}``.
        """
        if not _SHADOW_ID_RE.match(shadow_id):
            raise HTTPException(status_code=400, detail="invalid shadow_id")
        if format not in ("html", "pdf"):
            raise HTTPException(status_code=400, detail="format must be html or pdf")

        reports_dir = Path.home() / ".vibe-trading" / "shadow_reports"
        path = reports_dir / f"{shadow_id}.{format}"
        if not path.exists():
            raise HTTPException(status_code=404, detail=f"Shadow report not found: {shadow_id}.{format}")

        media_type = "text/html; charset=utf-8" if format == "html" else "application/pdf"
        return FileResponse(
            path,
            media_type=media_type,
            headers={"Content-Disposition": f'inline; filename="{shadow_id}.{format}"'},
        )

    @app.post("/upload", dependencies=[Depends(require_auth)])
    async def upload_file(file: UploadFile):
        """Upload any document or data file (max 50MB).

        Accepts most common formats: PDF, Word, Excel, PowerPoint, images,

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use format=html or format=pdf exactly (lowercase)
  2. Normalize the format value to lowercase client-side

Example fix

// before
?format=HTML
// after
?format=html
Defensive patterns

Strategy: validation

Validate before calling

fmt = fmt.lower()
assert fmt in ('html','pdf'), 'format must be html or pdf'

Prevention

When it happens

Trigger: GET /uploads/shadow-report?shadow_id=X&format=json or format=md; also 'HTML' (uppercase) fails the exact string match.

Common situations: Clients defaulting to json, typos like 'pd', or locale-casing differences where the caller sends 'HTML' instead of 'html'.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/d093828a0328ff69. Report an issue: GitHub.