dgtlmoon/changedetection.io · error · Non200ErrorCodeReceived

Non200ErrorCodeReceived

Error message

Non200ErrorCodeReceived

What it means

After the jq import succeeds, the input is checked with validate_jq_expression() and compiled with jq.compile(). If either raises ValueError, the validator reports the expression as invalid jq, embedding jq's compiler error message.

Source

Thrown at changedetectionio/content_fetchers/playwright.py:359

            except Exception as e:
                # https://github.com/dgtlmoon/changedetection.io/discussions/2122#discussioncomment-8241962
                logger.critical(f"Response from the browser/Playwright did not have a status_code! Response follows.")
                logger.critical(response)
                await context.close()
                await browser.close()
                raise PageUnloadable(url=url, status_code=None, message=str(e))

            if fetch_favicon:
                try:
                    self.favicon_blob = await self.page.evaluate(FAVICON_FETCHER_JS)
                    await self.page.request_gc()
                except Exception as e:
                    logger.error(f"Error fetching FavIcon info {str(e)}, continuing.")

            if self.status_code != 200 and not ignore_status_codes:
                screenshot = await capture_full_page_async(self.page, screenshot_format=self.screenshot_format, watch_uuid=watch_uuid, lock_viewport_elements=self.lock_viewport_elements)
                # Finally block will handle cleanup
                raise Non200ErrorCodeReceived(url=url, status_code=self.status_code, screenshot=screenshot)

            if not empty_pages_are_a_change and len((await self.page.content()).strip()) == 0:
                logger.debug("Content Fetcher > Content was empty, empty_pages_are_a_change = False")
                await context.close()
                await browser.close()
                raise EmptyReply(url=url, status_code=response.status)

            # Wrap remaining operations in try/finally to ensure cleanup
            try:
                # Run Browser Steps here
                if self.browser_steps:
                    try:
                        await self.iterate_browser_steps(start_url=url)
                    except BrowserStepsStepException:
                        # Finally block will handle cleanup
                        raise

                    await self.page.wait_for_timeout(extra_wait * 1000)

View on GitHub (pinned to 5d9c7c6da7)

Solutions

  1. Test the filter with the jq CLI or `python -c "import jq; jq.compile('...')"`
  2. Simplify the filter; check braces/quotes are balanced
  3. Ensure validate_jq_expression limits (length, banned tokens) aren't being hit and shorten the program

Example fix

# before
jq:.prices[] | select(.amount > 100 and
# after
jq:.prices[] | select(.amount > 100)
Defensive patterns

Strategy: validation

Validate before calling

import jq
from changedetectionio.html_tools import validate_jq_expression

def jq_ok(expr: str) -> bool:
    try:
        validate_jq_expression(expr)
        jq.compile(expr)
        return True
    except ValueError:
        return False

Type guard

def is_valid_jq(expr: str) -> bool:
    try:
        jq.compile(expr)
        return True
    except (ValueError, Exception):
        return False

Try / catch

try:
    jq.compile(expr)
except ValueError as e:
    # str(e) contains jq's compile error for display
    ...

Prevention

When it happens

Trigger: Submitting 'jq:' lines with syntax errors such as 'jq:.foo bar', unbalanced braces 'jq:{a:', or a guard-rules violation flagged by validate_jq_expression (e.g. disallowed constructs) — anything that makes jq.compile raise ValueError.

Common situations: Typos in jq filter programs; using jq CLI-only syntax not supported by the python binding's version; overly long programs caught by the built-in safety validation (validate_jq_expression enforces length/complexity limits).

Related errors


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