dgtlmoon/changedetection.io · error · ProcessorException
Cannot run, more than one price detected, this plugin is onl
Error message
Cannot run, more than one price detected, this plugin is only for product pages with ONE product, try the content-change detection mode.
What it means
A ProcessorException raised by the restock_diff processor when the page contained multiple price candidates and neither built-in extraction nor any plugin could resolve a single price. The restock processor is designed for single-product pages only, so ambiguous pricing aborts the check rather than guessing.
Source
Thrown at changedetectionio/processors/restock_diff/processor.py:539
# pattern as evaluator.py) so they're committed when update_watch runs
if _plugin_tokens:
watch['llm_last_tokens_used'] = _plugin_tokens
watch['llm_tokens_used_cumulative'] = (watch.get('llm_tokens_used_cumulative') or 0) + _plugin_tokens
# Plugin provided better data, use it
plugin_has_price = plugin_availability.get('price') is not None
plugin_has_availability = plugin_availability.get('availability') is not None
# Only use plugin data if it's actually better than what we have
if plugin_has_price or plugin_has_availability:
itemprop_availability = plugin_availability
logger.info(f"Using plugin-provided availability data for fetcher '{fetcher_name}' (built-in had price={has_price}, availability={has_availability}; plugin has price={plugin_has_price}, availability={plugin_has_availability})")
if not plugin_availability:
logger.debug("No item price/availability from plugins")
# If we had multiple prices and plugins also failed, NOW raise the exception
if multiple_prices_found and not itemprop_availability.get('price'):
raise ProcessorException(
message="Cannot run, more than one price detected, this plugin is only for product pages with ONE product, try the content-change detection mode.",
url=watch.get('url'),
status_code=self.fetcher.get_last_status_code(),
screenshot=self.fetcher.screenshot,
xpath_data=self.fetcher.xpath_data
)
# Something valid in get_itemprop_availability() by scraping metadata ?
if itemprop_availability.get('price') or itemprop_availability.get('availability'):
# Store for other usage. Wrap in Restock() so it's ALWAYS a Restock, never a plain
# dict: the built-in extruct path returns a Restock, but plugin fallbacks (e.g. the
# LLM restock scraper) return a plain dict. A plain dict here later blows up callers
# that use its helpers, e.g. watch['restock'].get_price_change_percent() on the
# watchlist (AttributeError -> 500 on the list page).
update_obj['restock'] = Restock(itemprop_availability)
if itemprop_availability.get('availability'):
# @todo: Configurable?View on GitHub (pinned to 5d9c7c6da7)
Solutions
- Switch the watch's processor to the content-change ('text_json_diff') mode as the message suggests
- Narrow the target: add an include filter/element selection covering just the single product's price node
- Use a more specific XHR/API URL for the single product instead of the HTML listing page
- Write/enable a plugin fetcher that returns a single definitive price
Defensive patterns
Strategy: validation
Validate before calling
from changedetectionio.processors import get_processor_module
# only use restock_diff on pages you know contain a single product
if not is_single_product_page(url):
watch['processor'] = 'text_json_diff' Try / catch
try:
handler.run_changedetection(watch, ...)
except ProcessorException as e:
if 'more than one price detected' in str(e):
watch['processor'] = 'text_json_diff' # auto-demote as the message suggests Prevention
- Reserve restock_diff for single product-detail URLs, never category/search pages
- Add a tight include filter around one product's price node
- Consider JSON-LD presence a prerequisite: product pages usually expose schema.org offers
When it happens
Trigger: Scraping a category/listing page or product page with variants where multiple price-looking values exist (multiple itemprop price tags, multiple currency patterns in text), and plugin fetchers also returned no definitive price/availability data.
Common situations: Pointing the 'stock/price restock' processor at a search results or category page; pages with crossed-out regular price + sale price + per-unit price; marketplace pages listing several offers.
Related errors
- No screenshot available. Ensure the watch is configured to u
- UUID: {watch.get('uuid')} - Screenshot comparison failed: {e
- Unable to extract restock data for this page unfortunately.
- {self.filter_config.include_filters}
- Processor module '{processor}' not found.
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/30887797ccd35398.
Report an issue: GitHub.