{"record":{"id":"c9eb5e95f9a810dd","repo":"dgtlmoon/changedetection.io","slug":"backup-archive-decompressed-size-total-uncompres","errorCode":null,"errorMessage":"Backup archive decompressed size ({total_uncompressed // (1024 * 1024)} MB) exceeds the {_MAX_DECOMPRESSED_BYTES // (1024 * 1024)} MB limit","messagePattern":"Backup archive decompressed size \\((.+?) MB\\) exceeds the (.+?) MB limit","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"changedetectionio/blueprint/backups/restore.py","lineNumber":66,"sourceCode":"    Returns a dict with counts: restored_groups, skipped_groups, restored_watches, skipped_watches.\n    Raises zipfile.BadZipFile if the stream is not a valid zip.\n    \"\"\"\n    from changedetectionio.model import Tag\n\n    restored_groups = 0\n    skipped_groups = 0\n    restored_watches = 0\n    skipped_watches = 0\n\n    current_tags = datastore.data['settings']['application'].get('tags', {})\n    current_watches = datastore.data['watching']\n\n    with tempfile.TemporaryDirectory() as tmpdir:\n        logger.debug(f\"Restore: extracting zip to {tmpdir}\")\n        with zipfile.ZipFile(zip_stream, 'r') as zf:\n            total_uncompressed = sum(m.file_size for m in zf.infolist())\n            if total_uncompressed > _MAX_DECOMPRESSED_BYTES:\n                raise ValueError(\n                    f\"Backup archive decompressed size ({total_uncompressed // (1024 * 1024)} MB) \"\n                    f\"exceeds the {_MAX_DECOMPRESSED_BYTES // (1024 * 1024)} MB limit\"\n                )\n            resolved_dest = os.path.realpath(tmpdir)\n            for member in zf.infolist():\n                member_dest = os.path.realpath(os.path.join(resolved_dest, member.filename))\n                if not member_dest.startswith(resolved_dest + os.sep) and member_dest != resolved_dest:\n                    raise ValueError(f\"Zip Slip path traversal detected in backup archive: {member.filename!r}\")\n                zf.extract(member, tmpdir)\n        logger.debug(\"Restore: zip extracted, scanning UUID directories\")\n\n        for entry in os.scandir(tmpdir):\n            if not entry.is_dir():\n                continue\n\n            uuid = entry.name\n            if not _UUID_RE.match(uuid):\n                logger.warning(f\"Restore: skipping non-UUID directory {uuid!r}\")","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/dgtlmoon/changedetection.io/blob/5d9c7c6da76340597243e8163c4f2439237fa0e8/changedetectionio/blueprint/backups/restore.py#L48-L84","documentation":"The multi-line expression validator supports JSONPath only in fields explicitly flagged allow_json. When a submitted line contains 'json:' and the field was constructed with allow_json=False, validation rejects it immediately with this message.","triggerScenarios":"Entering 'json:$.store.book[0].title' into a field whose ValidateMultiDataUrl/validator instance was created without allow_json=True (e.g. the CSS/filter XPath-only field instead of the 'Extract/Convert' text field).","commonSituations":"Users pasting JSON extraction rules into the wrong form field; plugin/custom watch forms that reuse the validator without enabling JSON support; UI not making clear which fields accept json: prefixes.","solutions":["Move the json: expression to a field that permits JSONPath (the extract_text / JSON-capable field)","If building a custom form, pass allow_json=True to the validator","Strip the 'json:' prefix if you intended a plain XPath"],"exampleFix":"# before\n# field: css filter (XPath only) -> json:$.a.b\n# after\n# field: 'Extract text before/after or JSON' -> json:$.a.b","handlingStrategy":"validation","validationCode":"def line_allowed(line: str, allow_json: bool) -> bool:\n    if 'json:' in line:\n        return allow_json\n    return True","typeGuard":"def is_jsonpath_line(line: str) -> bool:\n    return line.strip().lower().startswith('json:')","tryCatchPattern":null,"preventionTips":["Enter json: rules only in fields documented as JSON-capable","When building forms, explicitly decide allow_json per field","Disable/hide JSON inputs in the UI when allow_json=False"],"tags":["jsonpath","form-validation","changedetectionio"],"backgroundTag":"jsonpath-not-allowed","analyzedSha":"5d9c7c6da76340597243e8163c4f2439237fa0e8","analyzedAt":"2026-08-27T19:41:16.067Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}