HumanSignal/label-studio · error · ValueError
annotation "result" can't be parse from str to JSON
Error message
annotation "result" can't be parse from str to JSON
What it means
AnnotationSerializer.validate_result() accepts the annotation 'result' either as parsed JSON (list) or as a JSON string, which it json.loads()s. If the string cannot be parsed as JSON, ValueError is raised (note: ValueError, not DRF ValidationError, so it surfaces as a 500 unless caught).
Source
Thrown at label_studio/tasks/serializers.py:198
try:
return super().create(*args, **kwargs)
except IntegrityError as e:
errors = [
'UNIQUE constraint failed: task_completion.unique_id',
'duplicate key value violates unique constraint "task_completion_unique_id_key"',
]
if any([error in str(e) for error in errors]):
raise AnnotationDuplicateError()
raise
def validate_result(self, value):
data = value
# convert from str to json if need
if isinstance(value, str):
try:
data = json.loads(value)
except: # noqa: E722
raise ValueError('annotation "result" can\'t be parse from str to JSON')
# check result is list
if not isinstance(data, list):
raise ValidationError('annotation "result" field in annotation must be list')
# FIT-1669: collapse `(id, from_name, type)` collisions at the write boundary
# so the annotation record never persists duplicate-id rows.
return dedupe_annotation_result_list(data)
def _resolve_project_for_validation(self, data):
if 'task' in data:
return data['task'].project
if self.instance is not None:
return self.instance.project
task = self.context.get('task')
if task is not None:
return task.project
return NoneView on GitHub (pinned to 0b49e9b539)
Solutions
- Send result as an actual JSON array in the request body (correct Content-Type: application/json), not as a stringified blob
- If sending a string, ensure it is valid JSON: use json.dumps(obj) (double quotes, no trailing commas) — never str(obj) or repr(obj)
- Catch ValueError in custom code paths around serializer.is_valid() since this specific failure raises ValueError, not ValidationError
- Validate with json.loads(result) client-side before the request
Example fix
// before
payload = {"result": str(my_result_list)} # "[{'id': 1, ...}]" -> invalid JSON
// after
payload = {"result": json.dumps(my_result_list)} # or send the list itself Defensive patterns
Strategy: validation
Validate before calling
import json
def assert_result_string_is_json(value):
if isinstance(value, str):
try:
json.loads(value)
except json.JSONDecodeError as e:
raise ValueError(f"result string is not valid JSON: {e}") Type guard
def is_parsable_json_string(value) -> bool:
if not isinstance(value, str):
return True
try:
json.loads(value)
return True
except json.JSONDecodeError:
return False Try / catch
try:
ser = AnnotationSerializer(data=payload)
ser.is_valid(raise_exception=True)
except ValueError as e:
# validate_result raises ValueError (not ValidationError) on unparseable strings
logger.error("annotation result is not valid JSON: %s", e)
except Exception as e:
logger.error("annotation rejected: %s", e) Prevention
- Send result as a native JSON array (Content-Type: application/json), not a stringified blob
- Serialize with json.dumps, never str()/repr() of Python objects
- Validate with json.loads client-side before sending
- Catch ValueError separately from ValidationError around serializer.is_valid() since this path raises ValueError
When it happens
Trigger: POST/PUT of an annotation with result sent as a string that is not valid JSON — e.g. single-quoted JSON ({'a': 1}), Python repr of a dict, trailing commas, or a non-JSON string like "label-a" — to the annotations API or via AnnotationSerializer directly.
Common situations: Clients building the JSON string with Python str(dict) instead of json.dumps; form-data/text content types where the JSON string is preserved literally; copy-pasted results from logs; double-encoding mistakes.
Related errors
- annotation "result" field in annotation must be list
- Task item should be dict
- Unsupported or invalid JSON structure
- {connection validation error}
- exc.kwargs['report']
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/c211a7ced2414a31.
Report an issue: GitHub.