HumanSignal/label-studio · error · ValidationError

Failed to parse JSON file {self.file_name}: {extract_message

Error message

Failed to parse JSON file {self.file_name}: {extract_message(exc)}

What it means

read_tasks_list_from_json_streaming wraps any exception raised while parsing/iterating the JSON file into a single ValidationError that includes the file name and the underlying message via extract_message(exc). It is a catch-all transformer, so the root cause (JSONDecodeError, the 'Unsupported or invalid JSON structure' error, encoding errors, etc.) appears in the message text.

Source

Thrown at label_studio/data_import/models.py:218

                    # Single JSON object: parse once and yield a single-item batch
                    raw_data = file_handle.read()
                    try:
                        task_data = json.loads(raw_data)
                    except TypeError:
                        task_data = json.loads(raw_data.decode('utf8'))
                    formatted_task = self._format_task_for_json_streaming(task_data)
                    batch.append(formatted_task)

                else:
                    # Unknown/invalid JSON structure
                    raise ValidationError('Unsupported or invalid JSON structure')

                # Yield remaining tasks if any
                if batch:
                    yield batch

        except Exception as exc:
            raise ValidationError(f'Failed to parse JSON file {self.file_name}: {extract_message(exc)}')

    def _format_task_for_json_streaming(self, task):
        """Format task data for JSON streaming consistency with read_tasks_list_from_json"""
        # Handle different task types as in the original read_tasks_list_from_json method
        if isinstance(task, dict):
            if not task.get('data'):
                task = {'data': task}
        else:
            # If task is not a dict (e.g., list), wrap it in {'data': task}
            task = {'data': task}

        if not isinstance(task['data'], dict):
            raise ValidationError('Task item should be dict')
        return task

    def read_task_from_hypertext_body(self):
        logger.debug('Read 1 task from hypertext file {}'.format(self.filepath))
        body = self.content

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Read the wrapped inner message after 'Failed to parse JSON file ...:' and fix the underlying JSON syntax issue
  2. Run the file through a JSON linter / python -m json.tool to locate the syntax error
  3. Re-save the file as UTF-8 and as valid JSON (no trailing commas, comments, or envelope objects)

Example fix

// before: file contains BOM/UTF-16 or trailing comma
{"a": 1,}
// after: valid UTF-8 JSON
{"a": 1}
Defensive patterns

Strategy: try-catch

Validate before calling

import json
raw = open('tasks.json', 'rb').read()
text = raw.decode('utf8')  # raises on wrong encoding
json.loads(text)           # raises with position on bad syntax

Try / catch

try:
    for batch in fu.read_tasks_streaming():
        yield batch
except ValidationError as e:
    # e contains 'Failed to parse JSON file <name>: <inner cause>'
    raise ValueError(f"Fix JSON before import: {e}") from e

Prevention

When it happens

Trigger: Any exception inside the streaming read: invalid JSON syntax (json.loads failure), unsupported top-level structure, decode errors on non-UTF8 bytes, or I/O errors reading the file during read_tasks_streaming.

Common situations: Truncated or corrupted upload; file saved with wrong encoding (UTF-16); JSON with trailing commas or comments; uploading a CSV renamed to .json.

Understand the failure class

Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.

Related errors


AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29). Data as JSON: /api/errors/0e69cab5636de324. Report an issue: GitHub.