can1357/oh-my-pi · error · SyntaxError

Expected object key

Error message

Expected object key

What it means

Thrown by RelaxedJson.#key in strict mode when a key position inside an object contains no key characters — the current char is not a quote and not an identifier character. Partial mode returns an empty-string key instead of throwing.

Source

Thrown at packages/utils/src/json-parse.ts:351

			}
			if (this.#partial) return out;
			throw new SyntaxError("Expected ',' or ']' in array");
		}
	}

	#key(): string {
		const c = this.#s[this.#i];
		if (c === '"' || c === "'") return this.#string(this.#s.charCodeAt(this.#i));
		// Unquoted identifier key: read until a structural delimiter / whitespace.
		const start = this.#i;
		while (this.#i < this.#n) {
			const ch = this.#s[this.#i];
			if (ch === ":" || ch === "," || ch === "}" || isWhitespace(this.#s.charCodeAt(this.#i))) break;
			this.#i++;
		}
		if (this.#i === start) {
			if (this.#partial) return "";
			throw new SyntaxError("Expected object key");
		}
		return this.#s.slice(start, this.#i);
	}

	#string(quote: number): string {
		const s = this.#s;
		const n = this.#n;
		let i = this.#i + 1; // skip opening quote
		let out = "";
		let runStart = i;
		while (i < n) {
			const cc = s.charCodeAt(i);
			if (cc !== BACKSLASH && cc !== quote) {
				i++;
				continue;
			}
			if (cc === quote) {
				// Apostrophe / inner-quote recovery (a quote that isn't followed by a

View on GitHub (pinned to 9690622007)

Solutions

  1. Fix the input so each key is a quoted string or an identifier
  2. Check whether an interpolated key variable is empty in the code that builds the JSON
  3. Use parseStreamingJson if the input may be an incomplete streaming prefix
  4. Validate tool-call arguments against a schema and skip the malformed call rather than executing it

Example fix

// before
const v = parseJsonWithRepair(`{: 1}`); // SyntaxError: Expected object key
// after
const v = parseJsonWithRepair(`{"key": 1}`); // {key: 1}
Defensive patterns

Strategy: validation

Validate before calling

// Reject payloads where a punctuation char occupies a key position
const stripped = text.replace(/"(\\.|[^"\\])*"/g, '"S"');
const badKey = /\{\s*[:;,.]/.test(stripped) || /,\s*[:;]/.test(stripped);

Try / catch

try {
  const value = parseJsonWithRepair<T>(text);
} catch (err) {
  if (err instanceof SyntaxError && err.message === "Expected object key") {
    // reject the call; check the producing template for an empty/missing key variable
  } else throw err;
}

Prevention

When it happens

Trigger: parseJsonWithRepair with a stray delimiter where a key should be, e.g. '{: 1}', '{,}', '{"a": 1, :2}', or a punctuation char starting the key slot in strict mode (stray commas alone are already tolerated, so something like ':' or ';' must sit in the key position).

Common situations: Malformed LLM output with a stray colon or punctuation in the key slot; template interpolation producing '{: value}' when the key variable is empty; mangled output from an upstream serializer.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/e1844da822fec9ff. Report an issue: GitHub.