{"record":{"id":"56f8764878dfc9ea","repo":"NousResearch/hermes-agent","slug":"theme-has-no-colors-map-not-a-vs-code-color-th","errorCode":null,"errorMessage":"Theme has no \"colors\" map — not a VS Code color theme.","messagePattern":"Theme has no \"colors\" map — not a VS Code color theme\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/src/themes/vscode.ts","lineNumber":209,"sourceCode":"  keys: string[],\n  backdrop: string\n): { key: string; value: string } | null => {\n  for (const key of keys) {\n    const value = normalizeHex(typeof colors[key] === 'string' ? (colors[key] as string) : null, backdrop)\n\n    if (value) {\n      return { key, value }\n    }\n  }\n\n  return null\n}\n\nexport function convertVscodeColorTheme(raw: VscodeColorTheme, opts: ConvertOptions = {}): ConvertResult {\n  const colors = raw.colors && typeof raw.colors === 'object' ? (raw.colors as Record<string, unknown>) : null\n\n  if (!colors) {\n    throw new Error('Theme has no \"colors\" map — not a VS Code color theme.')\n  }\n\n  const derived: string[] = []\n\n  // Background first: it's the backdrop every other token flattens alpha over.\n  const backgroundHit = pick(\n    colors,\n    ['editor.background', 'editorPane.background', 'editorGroup.background'],\n    '#000000'\n  )\n\n  const dark = isDarkType(raw, backgroundHit?.value ?? '#1e1e1e')\n  const background = backgroundHit?.value ?? (dark ? '#1e1e1e' : '#ffffff')\n\n  if (!backgroundHit) {\n    derived.push('editor.background')\n  }\n","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/src/themes/vscode.ts#L191-L227","documentation":"Thrown by convertVscodeColorTheme when the parsed VS Code theme JSON has no usable 'colors' object. This converter maps VS Code editor colors onto a Hermes desktop palette; the colors map (editor.background, foreground, token colors, etc.) is the core input, so a theme that only ships tokenScopes or UI definitions without colors is rejected as not a color theme.","triggerScenarios":"Passing a theme JSON whose top level lacks 'colors' or has colors as a non-object (string/number), e.g. a pure TextMate token-scope theme or a language definition file.","commonSituations":"Selecting the wrong file from an extension's themes/ directory, or installing an extension whose theme contribution points at a scopes-only JSON.","solutions":["Open the JSON and verify it contains a \"colors\": { ... } object with editor.background/editor.foreground entries.","Pick the color theme file listed in the extension's package.json contributes.themes[].path, not adjacent token files.","If the extension legitimately has no colors, it cannot be converted — use a different extension."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"function hasColorsMap(raw: object): boolean {\n  return Boolean(raw.colors) && typeof raw.colors === 'object'\n}","typeGuard":"function isColorThemeRaw(raw: unknown): raw is { colors: Record<string, unknown> } {\n  return typeof raw === 'object' && raw !== null\n    && typeof (raw as { colors?: unknown }).colors === 'object'\n    && (raw as { colors?: unknown }).colors !== null\n}","tryCatchPattern":"try {\n  convertVscodeColorTheme(raw, { label })\n} catch (e) {\n  if (e instanceof Error && e.message.includes('no \"colors\" map'))\n    skipFile('Not a VS Code color theme (token-only)')\n  else throw e\n}","preventionTips":["Screen candidate JSON files for a colors object before conversion.","Drive imports from the extension manifest's contributes.themes list, not directory scans.","Fail per-file, not per-extension, so one bad file doesn't abort the whole import."],"tags":["desktop","themes","vscode","conversion"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}