dgtlmoon/changedetection.io · error · EmptyReply

EmptyReply

Error message

EmptyReply

What it means

When a submitted line starts with 'jq:', the validator tries `import jq`. If the Python jq binding package is not installed (ModuleNotFoundError), it rejects with 'jq not support not found' (sic). The jq module needs native compilation and is often unavailable, notably on Windows.

Source

Thrown at changedetectionio/content_fetchers/playwright.py:313

            )

            self.page = await context.new_page()

            # Listen for all console events and handle errors
            self.page.on("console", lambda msg: logger.debug(f"Playwright console: Watch URL: {url} {msg.type}: {msg.text} {msg.args}"))

            # Re-use as much code from browser steps as possible so its the same
            from changedetectionio.browser_steps.browser_steps import steppable_browser_interface
            browsersteps_interface = steppable_browser_interface(start_url=url)
            browsersteps_interface.page = self.page

            response = await browsersteps_interface.action_goto_url(value=url)

            if response is None:
                await context.close()
                await browser.close()
                logger.debug("Content Fetcher > Response object from the browser communication was none")
                raise EmptyReply(url=url, status_code=None)

            # In async_playwright, all_headers() returns a coroutine
            try:
                self.headers = await response.all_headers()
            except TypeError:
                # Fallback for sync version
                self.headers = response.all_headers()

            try:
                if self.webdriver_js_execute_code is not None and len(self.webdriver_js_execute_code):
                    await browsersteps_interface.action_execute_js(value=self.webdriver_js_execute_code, selector=None)
            except playwright._impl._errors.TimeoutError as e:
                await context.close()
                await browser.close()
                # This can be ok, we will try to grab what we could retrieve
                pass
            except Exception as e:
                logger.debug(f"Content Fetcher > Other exception when executing custom JS code {str(e)}")

View on GitHub (pinned to 5d9c7c6da7)

Solutions

  1. Install the binding: pip install jq (on Linux/macOS; needs build tools or wheel)
  2. On Windows, use a Docker-based deployment or stick to json: JSONPath instead of jq:
  3. Check your requirements/variant of the app includes the jq extra

Example fix

# before
jq:.foo // "default"   # jq package not installed
# after (no jq available)
json:$.foo
Defensive patterns

Strategy: type-guard

Validate before calling

def jq_available() -> bool:
    try:
        import jq  # noqa
        return True
    except ModuleNotFoundError:
        return False

Type guard

def jq_available() -> bool:
    try:
        import jq
        return True
    except ModuleNotFoundError:
        return False

Prevention

When it happens

Trigger: Entering a jq:... expression on an installation where the 'jq' PyPI package is missing — e.g. Windows builds of changedetection.io, slim Docker images, or environments where the optional dependency was not installed.

Common situations: Running changedetection.io on Windows or a container without the jq python package; switching a config from JSONPath to jq filters without installing the optional dependency.

Related errors


AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27). Data as JSON: /api/errors/dedc1d55ff7e6ecf. Report an issue: GitHub.