{"record":{"id":"2edb9e55049dc4e2","repo":"HumanSignal/label-studio","slug":"selecteditems-must-be-json-encoded-string-for-dict","errorCode":null,"errorMessage":"selectedItems must be JSON encoded string for dict: {\"all\": [true|false], \"excluded | included\": [...task_ids...]}. Found: {selected}","messagePattern":"selectedItems must be JSON encoded string for dict: (.+?)\\. Found: (.+?)","errorType":"validation","errorClass":"DataManagerException","httpStatus":400,"severity":"error","filePath":"label_studio/data_manager/functions.py","lineNumber":310,"sourceCode":"\n    # use filters and selected items from request if it's specified\n    else:\n        # query arguments from url\n        if 'query' in request.GET:\n            data = json.loads(unquote(request.GET['query']))\n        # data payload from body\n        else:\n            data = request.data\n\n        selected = data.get('selectedItems', {'all': True, 'excluded': []})\n        if not isinstance(selected, dict):\n            if isinstance(selected, str):\n                # try to parse JSON string\n                try:\n                    selected = json.loads(selected)\n                except Exception as e:\n                    logger.error(f'Error parsing selectedItems: {e}')\n                    raise DataManagerException(\n                        'selectedItems must be JSON encoded string for dict: {\"all\": [true|false], '\n                        '\"excluded | included\": [...task_ids...]}. '\n                        f'Found: {selected}'\n                    )\n            else:\n                raise DataManagerException(\n                    'selectedItems must be dict: {\"all\": [true|false], '\n                    '\"excluded | included\": [...task_ids...]}. '\n                    f'Found type: {type(selected)} with value: {selected}'\n                )\n        filters = data.get('filters', None)\n        ordering = data.get('ordering', [])\n        prepare_params = PrepareParams(\n            project=project.id, selectedItems=selected, data=data, filters=filters, ordering=ordering, request=request\n        )\n    return prepare_params\n\n","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/HumanSignal/label-studio/blob/0b49e9b53917880baf1dd85d574fe5541a9aafb2/label_studio/data_manager/functions.py#L292-L328","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["JSON-encode the selected items object before sending: JSON.stringify({all:false, excluded:[1,2]})","Validate the string parses with json.loads/JSON.parse before the call","Send it as a real JSON dict in the request body instead of a string field","Check logs (logger.error prints the parse error) to see the exact malformed value"],"exampleFix":"// before\ncurl -d 'selectedItems=[1, 2]' /api/tasks\n// after\ncurl -d 'selectedItems={\"all\":false,\"excluded\":[1,2]}' /api/tasks","handlingStrategy":"validation","validationCode":"let selected = payload.selectedItems;\nif (typeof selected === 'string') selected = JSON.parse(selected); // throws early with a clear message\nif (typeof selected !== 'object' || Array.isArray(selected) || !('all' in selected)) throw new Error('selectedItems must be an object of shape {all, included|excluded}');","typeGuard":"const isValidSelectedItems = (v) => v != null && typeof v === 'object' && !Array.isArray(v) && typeof v.all === 'boolean' && (Array.isArray(v.excluded) || Array.isArray(v.included));","tryCatchPattern":"try { JSON.parse(selectedItems); } catch (err) { throw new Error('selectedItems is not valid JSON: ' + err.message); }","preventionTips":["Always JSON.stringify the object; never interpolate objects into strings","Prefer sending selectedItems as a real JSON object in the body","Validate with a schema (zod/joi) before the request","Check server logs for 'Error parsing selectedItems' to find the malformed source"],"tags":["api","json","data-manager","request-format"],"backgroundTag":"malformed-json-parameter","analyzedSha":"0b49e9b53917880baf1dd85d574fe5541a9aafb2","analyzedAt":"2026-08-29T00:39:52.578Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}