NousResearch/hermes-agent · error
Theme file is not a JSON object.
Error message
Theme file is not a JSON object.
What it means
Thrown by parseVscodeTheme when the theme file text, after stripping comments and trailing commas, parses to a non-object (or null) — i.e. JSON.parse succeeded but the top level is a number, string, array, or empty. The parser intentionally tolerates JSONC (comments, trailing commas) but still requires a top-level object.
Source
Thrown at apps/desktop/src/themes/vscode.ts:83
/**
* Parse a VS Code theme file. These ship as JSONC (line/block comments and
* trailing commas), so a plain `JSON.parse` rejects most real-world files.
* Strips comments + trailing commas, then parses. Throws on hard syntax errors.
*/
export function parseVscodeTheme(text: string): VscodeColorTheme {
const stripped = text
// Block comments.
.replace(/\/\*[\s\S]*?\*\//g, '')
// Line comments (not inside strings — naive but fine for theme files).
.replace(/(^|[^:"'\\])\/\/[^\n\r]*/g, '$1')
// Trailing commas before } or ].
.replace(/,(\s*[}\]])/g, '$1')
const parsed: unknown = JSON.parse(stripped)
if (!parsed || typeof parsed !== 'object') {
throw new Error('Theme file is not a JSON object.')
}
return parsed as VscodeColorTheme
}
const isDarkType = (raw: VscodeColorTheme, background: string): boolean => {
const type = (raw.type ?? '').toLowerCase()
if (type.includes('light')) {
return false
}
if (type === 'dark' || type === 'hc' || type === 'hc-black' || type.includes('dark')) {
return true
}
// No usable `type` — bucket by background luminance.
return luminance(background) < 0.4View on GitHub (pinned to c896c09c42)
Solutions
- Confirm the file is a VS Code color theme (JSON object with a 'colors' map), not a token array or manifest.
- If the file contains '//' inside string values (URLs), escape or quote them so the naive comment-stripping does not corrupt the JSON.
- Validate the raw file with a JSONC-aware linter before import.
Defensive patterns
Strategy: validation
Validate before calling
function looksLikeThemeObject(text: string): boolean {
try {
// reuse same stripping rules minimally: must start with '{'
return text.trimStart().startsWith('{')
} catch { return false }
} Type guard
function isJsonObject(parsed: unknown): parsed is Record<string, unknown> {
return typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)
} Try / catch
try {
parseVscodeTheme(text)
} catch (e) {
if (e instanceof Error && e.message === 'Theme file is not a JSON object.')
rejectFile('Expected a JSON object theme file')
else if (e instanceof SyntaxError) rejectFile('Theme file is not valid JSON/JSONC')
else throw e
} Prevention
- Reject files whose first non-space character is '[' (token arrays) before parsing.
- Prefer theme files referenced by contributes.themes[].path over arbitrary JSON in the extension.
- Escape '//' inside string literals (URLs) or validate with a JSONC parser first.
When it happens
Trigger: Feeding a .json theme file that is actually an array (token arrays like some semantic-token themes), an empty file, a plain string, or a file whose comment-stripping regex mangled the content into a non-object.
Common situations: Pointing the importer at a semantic token or icon manifest instead of a color theme file; a theme file containing URLs with '//' that the naive line-comment regex truncated, leaving invalid JSON remnants.
Related errors
- "${result.extensionId}" does not contribute any color themes
- Theme has no "colors" map — not a VS Code color theme.
- Expected a Marketplace id like "publisher.extension".
- Marketplace install is only available in the desktop app.
- "${theme.name}" collides with a built-in theme.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/cefb21cdf7cc568a.
Report an issue: GitHub.