NanmiCoder/MediaCrawler · error · HTTPException

Not a file

Error message

Not a file

What it means

A precondition check in _create_browser_context: it refuses to build a Playwright BrowserContext when self.browser is None, i.e. _connect_via_cdp never ran or failed before a context was requested. It is a guard exception, not an external failure — the caller tried to use the manager before a successful CDP connection was established.

Source

Thrown at api/routers/data.py:107

            except Exception:
                continue

    # Sort by modification time (newest first)
    files.sort(key=lambda x: x["modified_at"], reverse=True)

    return {"files": files}


@router.get("/files/{file_path:path}")
async def get_file_content(file_path: str, preview: bool = True, limit: int = 100):
    """Get file content or preview"""
    full_path = DATA_DIR / file_path

    if not full_path.exists():
        raise HTTPException(status_code=404, detail="File not found")

    if not full_path.is_file():
        raise HTTPException(status_code=400, detail="Not a file")

    # Security check: ensure within DATA_DIR
    try:
        full_path.resolve().relative_to(DATA_DIR.resolve())
    except ValueError:
        raise HTTPException(status_code=403, detail="Access denied")

    if preview:
        # Return preview data
        try:
            if full_path.suffix == ".json":
                with open(full_path, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    if isinstance(data, list):
                        return {"data": data[:limit], "total": len(data)}
                    return {"data": data, "total": 1}
            elif full_path.suffix == ".csv":
                import csv

View on GitHub (pinned to d6f7c5bb90)

Solutions

  1. Ensure the connect step runs to completion before any context/page request — call _connect_via_cdp and only proceed on success
  2. Check the manager state before use: `if not cdp_manager.browser: await cdp_manager.connect(...)`
  3. If the connection may drop mid-session, wrap connect+context creation so a failed connect retries from launching the browser, not just context creation
  4. Hunt upstream for swallowed exceptions that let execution reach this guard with browser=None

Example fix

// before
browser_context = await self._create_browser_context(proxy, user_agent)

// after
if not self.browser:
    raise RuntimeError("Browser not connected")
browser_context = await self._create_browser_context(proxy, user_agent)
Defensive patterns

Strategy: validation

Validate before calling

async def ensure_connected(manager, playwright) -> None:
    if not getattr(manager, "browser", None) or not manager.browser.is_connected():
        await manager._connect_via_cdp(playwright)
    assert manager.browser and manager.browser.is_connected(), "connect step did not yield a live browser"
# call ensure_connected(manager, playwright) BEFORE _create_browser_context

Type guard

def manager_ready(manager) -> bool:
    browser = getattr(manager, "browser", None)
    return browser is not None and browser.is_connected()

Try / catch

try:
    ctx = await manager._create_browser_context(proxy, ua)
except RuntimeError as e:
    if "Browser not connected" in str(e):
        await manager.start()  # full reconnect, then retry once
        ctx = await manager._create_browser_context(proxy, ua)
    else:
        raise

Prevention

When it happens

Trigger: Calling _create_browser_context before _connect_via_cdp succeeds; after a previous connection dropped and self.browser was reset to None; an earlier connect_over_cdp exception was swallowed upstream so the manager is in an uninitialized state.

Common situations: Startup race: the crawler requests a page while Chrome/DevTools is still booting; a prior run's cleanup set browser=None and code reused the manager instance; exception handlers that log-and-continue past a failed connect then proceed to context creation.

Related errors


AI-assisted analysis of NanmiCoder/MediaCrawler@d6f7c5bb90 (2026-08-15). Data as JSON: /api/errors/456b0d10eb84c128. Report an issue: GitHub.