{"record":{"id":"29f838d1d7c8c787","repo":"NousResearch/hermes-agent","slug":"expected-a-marketplace-id-like-publisher-extensio-29f838","errorCode":null,"errorMessage":"Expected a Marketplace id like \"publisher.extension\".","messagePattern":"Expected a Marketplace id like \"publisher\\.extension\"\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/src/themes/install.ts","lineNumber":80,"sourceCode":"    name: vscodeThemeSlug(result.displayName),\n    label: result.displayName,\n    description: `VS Code · ${result.extensionId}`,\n    colors: light.palette,\n    darkColors: dark.palette,\n    ...(terminal ? { terminal } : {}),\n    ...(darkTerminal ? { darkTerminal } : {})\n  }\n}\n\n/**\n * Download a Marketplace extension and install the theme family it contributes\n * (see `buildThemeFromMarketplace`). Returns the single installed theme.\n */\nexport async function installVscodeThemeFromMarketplace(id: string): Promise<DesktopTheme> {\n  const trimmed = id.trim()\n\n  if (!MARKETPLACE_ID_RE.test(trimmed)) {\n    throw new Error('Expected a Marketplace id like \"publisher.extension\".')\n  }\n\n  const api = window.hermesDesktop?.themes\n\n  if (!api?.fetchMarketplace) {\n    throw new Error('Marketplace install is only available in the desktop app.')\n  }\n\n  const result = await api.fetchMarketplace(trimmed)\n\n  return installUserTheme(buildThemeFromMarketplace(result))\n}\n","sourceCodeStart":62,"sourceCodeEnd":93,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/src/themes/install.ts#L62-L93","documentation":"Thrown by installVscodeThemeFromMarketplace when the supplied id does not match MARKETPLACE_ID_RE — the expected 'publisher.extension' dotted form. The id is trimmed then validated before any download, so malformed input (bare name, URL, spaces, wrong casing pattern) is rejected up front.","triggerScenarios":"Calling installVscodeThemeFromMarketplace('dracula'), with a full marketplace URL like 'https://marketplace.visualstudio.com/items?itemName=...', or with extra characters that fail the regex.","commonSituations":"Users pasting the Marketplace page URL instead of the extension id, or typing only the extension half of the id and dropping the publisher prefix.","solutions":["Use the exact identifier from the Marketplace page's 'More Info -> Identifier' field, e.g. 'dracula-theme.theme-dracula'.","If you have a URL, extract the itemName query parameter's value instead of passing the whole URL.","Pre-validate input against the same pattern (/^[\\w.-]+\\.[\\w.-]+$/) before calling."],"exampleFix":"// before\ninstallVscodeThemeFromMarketplace('Dracula Official')\n\n// after\ninstallVscodeThemeFromMarketplace('dracula-theme.theme-dracula')","handlingStrategy":"validation","validationCode":"const MARKETPLACE_ID_RE = /^[\\w.-]+\\.[\\w.-]+$/ // mirror install.ts\n\nfunction extractMarketplaceId(input: string): string | null {\n  const fromUrl = input.match(/[?&]itemName=([\\w.-]+\\.[\\w.-]+)/)\n  const id = (fromUrl?.[1] ?? input).trim()\n  return MARKETPLACE_ID_RE.test(id) ? id : null\n}","typeGuard":"function isMarketplaceId(id: string): boolean {\n  return /^[\\w.-]+\\.[\\w.-]+$/.test(id.trim())\n}","tryCatchPattern":null,"preventionTips":["Copy the Identifier field from the Marketplace page, not the title or URL.","Parse itemName out of pasted URLs before passing on.","Validate the dotted shape in the input field's onChange and disable submit when invalid."],"tags":["desktop","themes","validation","marketplace"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}