tirth8205/code-review-graph · error · ValueError

expected JSON object key

Error message

expected JSON object key

What it means

Raised by _object_members while walking object members: the token in key position is not a JSON string (e.g. it's a number, brace, or literal). The parser expected '"key": value' pairs and found something that cannot be an object key. This indicates structurally invalid or truncated JSONC at the removal target.

Source

Thrown at code_review_graph/uninstall.py:280

        elif kind in ("{", "["):
            index = _skip_value(tokens, index)
            continue
        index += 1
    raise ValueError("unterminated JSON container")


def _object_members(tokens: Sequence[_Token], index: int) -> list[_Member]:
    if index >= len(tokens) or tokens[index].kind != "{":
        raise ValueError("expected JSON object")
    members: list[_Member] = []
    cursor = index + 1
    while cursor < len(tokens) and tokens[cursor].kind != "}":
        if tokens[cursor].kind == ",":  # trailing comma
            cursor += 1
            continue
        key_token = tokens[cursor]
        if key_token.kind != "string" or not isinstance(key_token.value, str):
            raise ValueError("expected JSON object key")
        if cursor + 1 >= len(tokens) or tokens[cursor + 1].kind != ":":
            raise ValueError("expected colon after JSON object key")
        value_index = cursor + 2
        value_end = _skip_value(tokens, value_index)
        comma_index = value_end if (
            value_end < len(tokens) and tokens[value_end].kind == ","
        ) else None
        members.append(
            _Member(key_token.value, cursor, value_index, value_end, comma_index)
        )
        cursor = value_end + 1 if comma_index is not None else value_end
    return members


def _array_elements(tokens: Sequence[_Token], index: int) -> list[_Element]:
    if index >= len(tokens) or tokens[index].kind != "[":
        raise ValueError("expected JSON array")
    elements: list[_Element] = []

View on GitHub (pinned to b58668751a)

Solutions

  1. Run the file through a strict JSON validator (after comment-stripping) and fix the malformed object
  2. Quote all object keys — JSONC only permits string keys
  3. If the file is user-owned and possibly hand-edited, verify structure with json.loads on the comment-stripped text before invoking removal
  4. Catch ValueError and skip editing the file, logging it for manual cleanup

Example fix

// before
{ mcpServers: { "x": {} } }  // unquoted key -> expected JSON object key

// after
{ "mcpServers": { "x": {} } }
Defensive patterns

Strategy: validation

Validate before calling

import json, re
def parses_as_json(text: str) -> bool:
    try:
        json.loads(re.sub(r"//[^\n]*|/\*.*?\*/", "", text, flags=re.S))
        return True
    except ValueError:
        return False

Try / catch

try:
    _remove_jsonc_paths(text, paths)
except ValueError:
    skip_file_and_log()  # do not rewrite malformed files

Prevention

When it happens

Trigger: Removing a key from an object that contains a bare identifier, number, or nested container in key position, e.g. {2: "x"} or a cut-off file ending right after '{'. Also when a previous member's value was mis-skipped due to malformed structure, landing the cursor on a non-string token.

Common situations: Hand-edited config with JS-style unquoted keys ({server: ...}); file truncated mid-edit by a crash; trailing garbage after a value; schema migration left an object where a scalar used to be so token alignment shifts.

Related errors


AI-assisted analysis of tirth8205/code-review-graph@b58668751a (2026-08-28). Data as JSON: /api/errors/739ee442e59338de. Report an issue: GitHub.