{"record":{"id":"18e0adc3ed82aeae","repo":"dgtlmoon/changedetection.io","slug":"validation-failed-join-error-details","errorCode":null,"errorMessage":"Validation failed: {'; '.join(error_details)}","messagePattern":"Validation failed: (.+?)","errorType":"http","errorClass":"BadRequest","httpStatus":400,"severity":"error","filePath":"changedetectionio/api/__init__.py","lineNumber":214,"sourceCode":"                            # match the OpenAPI server definitions, causing false positives.\n                            if isinstance(error, PathError):\n                                logger.debug(f\"API Call - Skipping path/server validation (delegated to Flask): {error}\")\n                                continue\n\n                            error_str = str(error)\n                            # Extract detailed schema errors from __cause__\n                            if hasattr(error, '__cause__') and hasattr(error.__cause__, 'schema_errors'):\n                                for schema_error in error.__cause__.schema_errors:\n                                    field = '.'.join(str(p) for p in schema_error.path) if schema_error.path else 'body'\n                                    msg = schema_error.message if hasattr(schema_error, 'message') else str(schema_error)\n                                    error_details.append(f\"{field}: {msg}\")\n                            else:\n                                error_details.append(error_str)\n\n                        # Only raise if we have actual validation errors (not path/server issues)\n                        if error_details:\n                            logger.error(f\"API Call - Validation failed: {'; '.join(error_details)}\")\n                            raise BadRequest(f\"Validation failed: {'; '.join(error_details)}\")\n            except BadRequest:\n                # Re-raise BadRequest exceptions (validation failures)\n                raise\n            except Exception as e:\n                # If OpenAPI spec loading fails, log but don't break existing functionality\n                logger.critical(f\"OpenAPI validation warning for {operation_id}: {e}\")\n                abort(500)\n            return f(*args, **kwargs)\n        return wrapper\n    return decorator\n\n# Import all API resources\nfrom .Watch import Watch, WatchHistory, WatchSingleHistory, WatchHistoryDiff, CreateWatch, WatchFavicon\nfrom .Tags import Tags, Tag\nfrom .Import import Import\nfrom .SystemInfo import SystemInfo\nfrom .Spec import Spec\nfrom .Notifications import Notifications","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/dgtlmoon/changedetection.io/blob/5d9c7c6da76340597243e8163c4f2439237fa0e8/changedetectionio/api/__init__.py#L196-L232","documentation":"A catch-all bare `except:` in the XPath validator catches any non-XPathEvalError exception thrown while compiling the expression (or while acquiring the lxml lock / building the parser). It signals an unexpected system-level failure rather than a pure syntax error, and masks the original exception's details.","triggerScenarios":"lxml raising MemoryError, KeyboardInterrupt-style exceptions, parser instantiation failure, or lxml_guard lock errors while tree.xpath(line) runs; any unexpected exception type other than etree.XPathEvalError escaping the compile step.","commonSituations":"Broken lxml installation or version mismatch where html.fromstring or the shared parser misbehaves; concurrency issues around the shared lxml parser; thread interruption during validation. Rare in practice; almost all bad input hits the XPathEvalError branch instead.","solutions":["Check server logs / reproduce the compile locally to find the real exception","Verify lxml is properly installed and version-matched (pip install -U lxml) and the parser is not shared unsafely across threads","If you control the code, log the real exception before raising the generic message"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"null","typeGuard":null,"tryCatchPattern":"try:\n    tree.xpath(expr)\nexcept etree.XPathEvalError:\n    handle_syntax_error()\nexcept Exception as e:\n    log.exception('unexpected lxml failure')\n    handle_system_error(e)","preventionTips":["Pin a known-good lxml version","Don't share a single parser object across threads without a lock","Log the real exception; bare except: hides root causes"],"tags":["xpath","lxml","catch-all","unexpected-exception"],"backgroundTag":"xpath-expression-invalid","analyzedSha":"5d9c7c6da76340597243e8163c4f2439237fa0e8","analyzedAt":"2026-08-27T19:41:16.067Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}