{"record":{"id":"ec152fa9af5348f0","repo":"HumanSignal/label-studio","slug":"file-key-is-not-a-json-jsonl-parquet-file-onl","errorCode":null,"errorMessage":"File \"{key}\" is not a JSON/JSONL/Parquet file. Only .json, .jsonl, and .parquet files can be processed.\\nIf you're trying to import non-JSON data (images, audio, text, etc.), edit storage settings and enable \"Tasks\" import method","messagePattern":"File \"(.+?)\" is not a JSON/JSONL/Parquet file\\. Only \\.json, \\.jsonl, and \\.parquet files can be processed\\.\\\\nIf you're trying to import non-JSON data \\(images, audio, text, etc\\.\\), edit storage settings and enable \"Tasks\" import method","errorType":"exception","errorClass":"UnsupportedFileFormatError","httpStatus":null,"severity":"error","filePath":"label_studio/io_storages/base_models.py","lineNumber":714,"sourceCode":"            tasks_existed += link_class.objects.filter(key__in=existing_keys, storage=self.id).count()\n            self.info_update_progress(last_sync_count=tasks_created, tasks_existed=tasks_existed)\n\n            for key in deduplicated_keys:\n                if key in existing_keys:\n                    logger.debug(f'{self.__class__.__name__} already has tasks linked to {key=}')\n                    continue\n\n                logger.debug(f'{self}: found new key {key}')\n\n                # Check if file should be processed as JSON based on extension\n                # Skip non-JSON files if use_blob_urls is False\n                if check_file_extension and not self.use_blob_urls:\n                    _, ext = os.path.splitext(key.lower())\n                    # Only process files with JSON/JSONL/PARQUET extensions\n                    json_extensions = {'.json', '.jsonl', '.parquet'}\n\n                    if ext and ext not in json_extensions:\n                        raise UnsupportedFileFormatError(\n                            f'File \"{key}\" is not a JSON/JSONL/Parquet file. Only .json, .jsonl, and .parquet files can be processed.\\n'\n                            f\"If you're trying to import non-JSON data (images, audio, text, etc.), \"\n                            f'edit storage settings and enable \"Tasks\" import method'\n                        )\n\n                try:\n                    link_objects = self.get_data(key)\n                except (UnicodeDecodeError, json.decoder.JSONDecodeError) as exc:\n                    logger.debug(exc, exc_info=True)\n                    raise ValueError(\n                        f'Error loading JSON from file \"{key}\".\\nIf you\\'re trying to import non-JSON data '\n                        f'(images, audio, text, etc.), edit storage settings and enable '\n                        f'\"Tasks\" import method'\n                    )\n\n                for link_object in link_objects:\n                    # TODO: batch this loop body with add_task -> add_tasks in a single bulk write.\n                    # See DIA-2062 for prerequisites","sourceCodeStart":696,"sourceCodeEnd":732,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/io_storages/base_models.py#L696-L732","documentation":"UnsupportedFileFormatError is raised by _scan_and_create_links during a storage sync when a found object's extension is not .json/.jsonl/.parquet and the storage is in JSON-import mode (use_blob_urls False, check_file_extension enabled). The JSON storage type can only parse structured data files, so binary/asset files are rejected instead of becoming tasks.","triggerScenarios":"Running scan_and_create_links on a JSON import storage whose bucket/directory contains .jpg/.png/.txt/.csv files; adding data assets to the same path the JSON storage syncs from.","commonSituations":"Pointing an import storage at a bucket holding both images and annotation JSON; users who intended the 'Treat every bucket object as a source URL' (Tasks/blob-urls) storage mode but left the storage on JSON import; files uploaded without extension (or uppercase fine — lowercased) being skipped.","solutions":["Remove non-.json/.jsonl/.parquet files from the synced location, or move JSON task files into a dedicated prefix/directory","If you want images/audio to become tasks directly, edit the storage settings and switch import method to 'Tasks' (treat as source URLs / use_blob_urls) instead of JSON parsing","Rename/move files that are JSON but have a wrong extension (e.g. .txt) so they end in .json/.jsonl/.parquet","Disable check_file_extension in code if you intentionally want all keys attempted as JSON"],"exampleFix":"// before (bucket contains img01.png and tasks.json -> sync raises)\nstorage.sync()\n// after: filter the storage prefix to a JSON-only path\nstorage.prefix = 'tasks-json/'\nstorage.save()\nstorage.sync()","handlingStrategy":"validation","validationCode":"import os\nALLOWED = {'.json', '.jsonl', '.parquet'}\ndef files_are_supported(keys):\n    bad = [k for k in keys if os.path.splitext(k.lower())[1] not in ALLOWED]\n    return not bad, bad","typeGuard":"def is_json_like(key):\n    import os\n    return os.path.splitext(key.lower())[1] in {'.json', '.jsonl', '.parquet'}","tryCatchPattern":"from label_studio.io_storages.base_models import UnsupportedFileFormatError\ntry:\n    storage.scan_and_create_links()\nexcept UnsupportedFileFormatError as e:\n    logger.error('Non-JSON object in storage: %s', e)\n    # move the file or switch storage import method to Tasks","preventionTips":["Keep JSON task files in a dedicated bucket prefix separate from media assets","Use the 'Tasks' (blob URL) storage mode when syncing images/audio","Never rename non-JSON files to .json","Preview bucket contents before enabling auto-sync"],"tags":["storage","import","file-extension","sync"],"backgroundTag":"unsupported-file-format","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}