HumanSignal/label-studio · error · DataManagerException

selectedItems must be JSON encoded string for dict: {"all":

Error message

selectedItems must be JSON encoded string for dict: {"all": [true|false], "excluded | included": [...task_ids...]}. Found: {selected}

What it means

get_prepare_params accepts selectedItems either as a dict or as a JSON-encoded string of the expected shape {"all": bool, "excluded|included": [task_ids]}. If the value is a string but json.loads fails, it raises DataManagerException telling the caller the string must be valid JSON of that shape.

Source

Thrown at label_studio/data_manager/functions.py:310

    # use filters and selected items from request if it's specified
    else:
        # query arguments from url
        if 'query' in request.GET:
            data = json.loads(unquote(request.GET['query']))
        # data payload from body
        else:
            data = request.data

        selected = data.get('selectedItems', {'all': True, 'excluded': []})
        if not isinstance(selected, dict):
            if isinstance(selected, str):
                # try to parse JSON string
                try:
                    selected = json.loads(selected)
                except Exception as e:
                    logger.error(f'Error parsing selectedItems: {e}')
                    raise DataManagerException(
                        'selectedItems must be JSON encoded string for dict: {"all": [true|false], '
                        '"excluded | included": [...task_ids...]}. '
                        f'Found: {selected}'
                    )
            else:
                raise DataManagerException(
                    'selectedItems must be dict: {"all": [true|false], '
                    '"excluded | included": [...task_ids...]}. '
                    f'Found type: {type(selected)} with value: {selected}'
                )
        filters = data.get('filters', None)
        ordering = data.get('ordering', [])
        prepare_params = PrepareParams(
            project=project.id, selectedItems=selected, data=data, filters=filters, ordering=ordering, request=request
        )
    return prepare_params

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. JSON-encode the selected items object before sending: JSON.stringify({all:false, excluded:[1,2]})
  2. Validate the string parses with json.loads/JSON.parse before the call
  3. Send it as a real JSON dict in the request body instead of a string field
  4. Check logs (logger.error prints the parse error) to see the exact malformed value

Example fix

// before
curl -d 'selectedItems=[1, 2]' /api/tasks
// after
curl -d 'selectedItems={"all":false,"excluded":[1,2]}' /api/tasks
Defensive patterns

Strategy: validation

Validate before calling

let selected = payload.selectedItems;
if (typeof selected === 'string') selected = JSON.parse(selected); // throws early with a clear message
if (typeof selected !== 'object' || Array.isArray(selected) || !('all' in selected)) throw new Error('selectedItems must be an object of shape {all, included|excluded}');

Type guard

const isValidSelectedItems = (v) => v != null && typeof v === 'object' && !Array.isArray(v) && typeof v.all === 'boolean' && (Array.isArray(v.excluded) || Array.isArray(v.included));

Try / catch

try { JSON.parse(selectedItems); } catch (err) { throw new Error('selectedItems is not valid JSON: ' + err.message); }

Prevention

When it happens

Trigger: Passing selectedItems as a raw, non-JSON string — e.g. selectedItems=all, selectedItems=[1,2] (Python repr with single quotes), a double-encoded/HTML-escaped value, or form-encoded data where the JSON got mangled.

Common situations: curl calls without quoting the JSON body; frontend sending str(selected_items) of a Python/JS object; template interpolation inserting single-quoted reprs; double URL-encoding stripping quotes.

Related errors


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