{"record":{"id":"13fbfef5546dfb62","repo":"langflow-ai/langflow","slug":"uploaded-file-is-not-a-valid-zip-archive-exc","errorCode":null,"errorMessage":"Uploaded file is not a valid ZIP archive: {exc}","messagePattern":"Uploaded file is not a valid ZIP archive: (.+?)","errorType":"http","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"src/backend/base/langflow/api/utils/zip_utils.py","lineNumber":38,"sourceCode":"    \"\"\"Result of synchronous ZIP extraction, including warnings to log after.\"\"\"\n\n    flows: list[dict] = field(default_factory=list)\n    warnings: list[str] = field(default_factory=list)\n\n\ndef _extract_flows_sync(contents: bytes) -> _ZipExtractionResult:\n    \"\"\"Synchronous helper that performs all blocking ZIP I/O.\n\n    Raises:\n        ValueError: If the ZIP is corrupt or contains more than MAX_ZIP_ENTRIES JSON files.\n    \"\"\"\n    result = _ZipExtractionResult()\n\n    try:\n        zf = zipfile.ZipFile(io.BytesIO(contents), \"r\")\n    except zipfile.BadZipFile as exc:\n        msg = f\"Uploaded file is not a valid ZIP archive: {exc}\"\n        raise ValueError(msg) from exc\n\n    with zf:\n        json_entries = [info for info in zf.infolist() if info.filename.lower().endswith(\".json\")]\n\n        if len(json_entries) > MAX_ZIP_ENTRIES:\n            msg = f\"ZIP contains {len(json_entries)} JSON entries, exceeding the limit of {MAX_ZIP_ENTRIES}\"\n            raise ValueError(msg)\n\n        for info in json_entries:\n            if info.file_size > MAX_ENTRY_UNCOMPRESSED_BYTES:\n                result.warnings.append(\n                    f\"Skipping ZIP entry '{info.filename}': uncompressed size \"\n                    f\"{info.file_size} exceeds limit of {MAX_ENTRY_UNCOMPRESSED_BYTES} bytes\"\n                )\n                continue\n            try:\n                raw = zf.read(info.filename)\n                if len(raw) > MAX_ENTRY_UNCOMPRESSED_BYTES:","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/utils/zip_utils.py#L20-L56","documentation":"Raised by _extract_flows_sync in zip_utils.py when zipfile.ZipFile cannot parse the uploaded bytes — Python raises zipfile.BadZipFile for corrupt, truncated, or non-ZIP content, and the helper converts it to ValueError with this message. The flows-import endpoint catches it and returns a 4xx to the client. It means the bytes received were not a readable ZIP archive.","triggerScenarios":"POST /api/v1/flows/upload/ (or any flows-import route using _extract_flows_sync) with a file that is not a ZIP: a bare .json flow file, a .tar.gz, a text file, or a ZIP truncated by a proxy/upload limit mid-transfer.","commonSituations":"Exporting a single flow from the Langflow UI (which downloads JSON, not ZIP) and re-uploading it directly; client-side encoding setting the wrong multipart field name so the server reads a different part; uploads truncated by nginx client_max_body_size or similar proxies.","solutions":["Confirm the uploaded file actually is a ZIP (unzip -t file.zip locally) and re-export a real ZIP bundle","If you have a single .json flow, use the JSON import endpoint or wrap it: zip flows.zip flow.json","Check for proxy/upload truncation: compare the file size/hash before upload vs on the server","Verify the multipart field name and filename match what the endpoint expects (with .zip extension)"],"exampleFix":"# before\ncurl -F \"file=@myflow.json\" /api/v1/flows/upload/\n# after\ncurl -F \"file=@flows.zip\" /api/v1/flows/upload/","handlingStrategy":"validation","validationCode":"import zipfile, io\n\ndef is_valid_flow_zip(path: str) -> bool:\n    try:\n        with zipfile.ZipFile(path) as zf:\n            return zf.testzip() is None\n    except zipfile.BadZipFile:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    result = import_flows(zip_bytes)\nexcept ValueError as e:\n    if \"not a valid ZIP archive\" in str(e):\n        if looks_like_json(zip_bytes):\n            result = import_flow_json(zip_bytes)   # single-flow fallback path\n        else:\n            raise\n    else:\n        raise","preventionTips":["Validate with zipfile.ZipFile locally before every upload","Export ZIP bundles from the UI's bulk-export action, not single-flow JSON downloads","Compare file size before/after transfer to catch proxy truncation"],"tags":["zip","upload","import","validation"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}