HumanSignal/label-studio · error · DataManagerException

selectedItems must be dict: {"all": [true|false], "excluded

Error message

selectedItems must be dict: {"all": [true|false], "excluded | included": [...task_ids...]}. Found type: {type(selected)} with value: {selected}

What it means

get_prepare_params requires selectedItems to be a dict (or a JSON string that parses to the expected shape). If the value is neither a string nor a dict — e.g. a list, number, or bool — it raises DataManagerException stating the required dict shape and the offending type/value.

Source

Thrown at label_studio/data_manager/functions.py:316

        # 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


def get_prepared_queryset(request, project):
    prepare_params = get_prepare_params(request, project)
    queryset = Task.prepared.only_filtered(prepare_params=prepare_params)
    return queryset

View on GitHub (pinned to 0b49e9b539)

Solutions

  1. Wrap the ids: send {"all": false, "included": [ids]} or {"all": true, "excluded": [ids]}`
  2. Ensure the client serializes an object, not an array, for selectedItems
  3. Check the API version/docs for the expected selectedItems schema
  4. Add client-side validation that typeof selectedItems === 'object' && !Array.isArray(...)

Example fix

// before
{"selectedItems": [12, 34]}
// after
{"selectedItems": {"all": false, "included": [12, 34]}}
Defensive patterns

Strategy: type-guard

Validate before calling

const sel = payload.selectedItems;
if (sel === null || typeof sel !== 'object' || Array.isArray(sel)) throw new Error('selectedItems must be {"all":bool,"included|excluded":[ids]}');

Type guard

const isSelectedItemsDict = (v) => typeof v === 'object' && v !== null && !Array.isArray(v) && typeof v.all === 'boolean';

Try / catch

try { await submit(payload); } catch (e) { if (/selectedItems must be dict/.test(e.message)) { payload.selectedItems = { all: false, included: payload.selectedItems }; await submit(payload); } else { throw e; } }

Prevention

When it happens

Trigger: Passing selectedItems as a bare list [1,2], an integer id, true/false, or null directly in the request body instead of the wrapper object {"all":bool,"excluded|included":[ids]}.

Common situations: Frontend code sending the raw selected-ids array; forgetting to wrap ids in the all/excluded/included envelope; schema drift between an older API version (plain id list) and the current one.

Related errors


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