D4Vinci/Scrapling · error · RuntimeError

Request failed

Error message

Request failed

What it means

A defensive trailing raise at the end of the retry loop in StealthySession.fetch(). In normal flow the loop either returns a Response or re-raises the last exception on the final attempt (the code path even carries `# pragma: no cover`), so this line only fires if the retry loop exits without returning or raising — effectively unreachable except through control-flow anomalies.

Source

Thrown at scrapling/engines/_browsers/_stealth.py:300

                    return response

                except Exception as e:
                    page_info.mark_error()
                    if attempt < self._config.retries - 1:
                        if is_proxy_error(e):
                            log.warning(
                                f"Proxy '{proxy}' failed (attempt {attempt + 1}) | Retrying in {self._config.retry_delay}s..."
                            )
                        else:
                            log.warning(
                                f"Attempt {attempt + 1} failed: {e}. Retrying in {self._config.retry_delay}s..."
                            )
                        time_sleep(self._config.retry_delay)
                    else:
                        log.error(f"Failed after {self._config.retries} attempts: {e}")
                        raise

        raise RuntimeError("Request failed")  # pragma: no cover


class AsyncStealthySession(AsyncSession, StealthySessionMixin):
    """An async Stealthy Browser session manager with page pooling."""

    __slots__ = (
        "_config",
        "_context_options",
        "_browser_options",
        "_user_data_dir",
        "_headers_keys",
    )

    def __init__(self, **kwargs: Unpack[StealthSession]):
        """A Browser session manager with page pooling, it's using a persistent browser Context by default with a temporary user profile directory.

        :param headless: Run the browser in headless/hidden (default), or headful/visible mode.
        :param disable_resources: Drop requests for unnecessary resources for a speed boost.

View on GitHub (pinned to 5d213a2d47)

Solutions

  1. Inspect the traceback and the scrapling version; report it upstream since the real failure exception was swallowed
  2. Update/patch scrapling to a release where the retry loop's control flow is correct
Defensive patterns

Strategy: try-catch

Try / catch

try:
    resp = session.fetch(url)
except RuntimeError:
    log.exception('internal retry-loop failure')
    raise

Prevention

When it happens

Trigger: Only reachable if the for-attempt loop body completes every iteration without returning a Response and without raising — which the current code structure prevents (last attempt re-raises). Practically never seen in the wild.

Common situations: Virtually none; if you see this message it indicates an internal control-flow change/bug in scrapling itself rather than a user mistake.

Related errors


AI-assisted analysis of D4Vinci/Scrapling@5d213a2d47 (2026-08-14). Data as JSON: /api/errors/57bfdbd10c9d3a87. Report an issue: GitHub.