{"record":{"id":"acf1bd4859b78e5e","repo":"FoundationAgents/MetaGPT","slug":"expecting-value","errorCode":null,"errorMessage":"Expecting value","messagePattern":"Expecting value","errorType":"exception","errorClass":"JSONDecodeError","httpStatus":null,"severity":"error","filePath":"metagpt/utils/custom_decoder.py","lineNumber":166,"sourceCode":"        # the JSON key separator is \": \" or just \":\".\n        if s[end : end + 1] != \":\":\n            end = _w(s, end).end()\n            if s[end : end + 1] != \":\":\n                raise JSONDecodeError(\"Expecting ':' delimiter\", s, end)\n        end += 1\n\n        try:\n            if s[end] in _ws:\n                end += 1\n                if s[end] in _ws:\n                    end = _w(s, end + 1).end()\n        except IndexError:\n            pass\n\n        try:\n            value, end = scan_once(s, end)\n        except StopIteration as err:\n            raise JSONDecodeError(\"Expecting value\", s, err.value) from None\n        pairs_append((key, value))\n        try:\n            nextchar = s[end]\n            if nextchar in _ws:\n                end = _w(s, end + 1).end()\n                nextchar = s[end]\n        except IndexError:\n            nextchar = \"\"\n        end += 1\n\n        if nextchar == \"}\":\n            break\n        elif nextchar != \",\":\n            raise JSONDecodeError(\"Expecting ',' delimiter\", s, end - 1)\n        end = _w(s, end).end()\n        nextchar = s[end : end + 1]\n        end += 1\n        if nextchar != '\"':","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/FoundationAgents/MetaGPT/blob/11cdf466d042aece04fc6cfd13b28e1a70341b1f/metagpt/utils/custom_decoder.py#L148-L184","documentation":"Raised by MetaGPT's custom JSON decoder while parsing an object: after a key and colon, scan_once could not find any recognizable value (the internal iterator raised StopIteration, converted to JSONDecodeError 'Expecting value'). This decoder is a patched copy of the stdlib json scanner that additionally tolerates single quotes, triple quotes and other LLM-style JSON quirks. It still rejects a value position that is empty or starts with an invalid token.","triggerScenarios":"Calling the decoder (e.g. metagpt.utils.custom_decoder.JSONDecoder / repair_partial_json on LLM output) on text like {\"a\": } (missing value), {\"a\": ,\"b\":1}, or a value beginning with a character that is not a valid JSON value start (e.g. {\"a\": NaN-style tokens the scanner does not accept, or unquoted barewords other than true/false/null).","commonSituations":"Parsing raw LLM responses where the model omitted a value, emitted Python literals (None, NaN) instead of JSON (null, NaN is invalid in strict JSON), or truncated output cut a value off. Also occurs when repair-style decoding is applied to text that only looks partially like JSON.","solutions":["Inspect the reported position in the input string to see the exact token that failed, and fix the malformed value.","Pre-sanitize LLM output: replace Python literals with JSON ones (None->null, True->true, False->false) before decoding.","If the text may be truncated, wrap with a repair/partial-JSON routine or feed the output through metagpt's own code extraction (e.g. extract JSON blocks) instead of decoding the whole message.","Catch json.JSONDecodeError and retry the LLM call asking for strictly valid JSON."],"exampleFix":"// before\nimport json\nobj = json.loads(llm_output)  # ValueError: Expecting value on '{\"a\": }'\n\n// after\nfrom metagpt.utils.common import output_parser\nobj = output_parser.parse_json_with_markdown_code(llm_output)  # extracts+repairs the JSON block first","handlingStrategy":"try-catch","validationCode":"import json\ntext = llm_output.strip()\ntry:\n    json.loads(text)\nexcept json.JSONDecodeError as e:\n    print('not valid JSON yet:', e.msg, 'at pos', e.pos)","typeGuard":"def is_parseable_json(text: str) -> bool:\n    try:\n        json.loads(text)\n        return True\n    except (json.JSONDecodeError, ValueError):\n        return False","tryCatchPattern":"from json import JSONDecodeError\ntry:\n    obj = decoder.decode(s)\nexcept JSONDecodeError as e:\n    # e.msg, e.pos locate the failure; log context around pos\n    logger.warning('JSON decode failed: %s at %d', e.msg, e.pos)\n    obj = repair_and_retry(s)  # sanitize None/True/False or re-ask the LLM","preventionTips":["Always json.dumps when producing JSON programmatically; never build it by string concatenation.","Extract fenced ```json blocks from LLM output before decoding.","Map Python literals to JSON (None->null, True/False->true/false) before parsing.","Feed JSONDecodeError position info back into a repair loop instead of guessing."],"tags":["json","parsing","llm-output"],"backgroundTag":null,"analyzedSha":"11cdf466d042aece04fc6cfd13b28e1a70341b1f","analyzedAt":"2026-08-14T23:20:02.994Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}