{"record":{"id":"c3d3ad718b24ef49","repo":"NousResearch/hermes-agent","slug":"extension-id-has-no-published-versions","errorCode":null,"errorMessage":"Extension \"${id}\" has no published versions.","messagePattern":"Extension \"(.+?)\" has no published versions\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/vscode-marketplace.ts","lineNumber":113,"sourceCode":"async function resolveExtension(id) {\n  const json = await queryGallery({\n    // FilterType 7 = ExtensionName (the full publisher.extension id).\n    filters: [{ criteria: [{ filterType: 7, value: id }], pageNumber: 1, pageSize: 1 }],\n    // Flags: IncludeFiles | IncludeVersionProperties | IncludeAssetUri |\n    // IncludeCategoryAndTags | IncludeLatestVersionOnly = 914.\n    flags: 914\n  })\n\n  const extension = json?.results?.[0]?.extensions?.[0]\n\n  if (!extension) {\n    throw new Error(`Extension \"${id}\" was not found on the Marketplace.`)\n  }\n\n  const version = extension.versions?.[0]\n\n  if (!version) {\n    throw new Error(`Extension \"${id}\" has no published versions.`)\n  }\n\n  const asset = (version.files ?? []).find(file => file.assetType === VSIX_ASSET_TYPE)\n  const vsixUrl = asset?.source\n\n  if (!vsixUrl) {\n    throw new Error(`Could not find a downloadable package for \"${id}\".`)\n  }\n\n  return { displayName: extension.displayName || id, vsixUrl }\n}\n\n/** POST an ExtensionQuery payload and return the parsed gallery response. */\nasync function queryGallery(payload, { maxBytes = 4 * 1024 * 1024 } = {}) {\n  const body = JSON.stringify(payload)\n\n  const raw = await request(GALLERY_QUERY_URL, {\n    method: 'POST',","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/electron/vscode-marketplace.ts#L95-L131","documentation":"Thrown by resolveExtension() when the Marketplace returns a matching extension object but extension.versions[0] is missing. The query uses IncludeLatestVersionOnly (flags 914), so a healthy listing always carries at least one version; an empty one means the listing is in a broken or partial state on the gallery side.","triggerScenarios":"queryGallery returns extensions[0] but extension.versions is undefined or [] — an extension unlisted mid-publish, gallery replication lag right after a version removal, or a stunted/truncated response from a proxy or CDN.","commonSituations":"Extension temporarily unpublished while a new version is validated; rare gallery inconsistency; corporate proxy truncating the JSON body so the versions field is lost.","solutions":["Retry after a short delay with backoff — transient gallery states usually resolve within minutes.","Verify the extension page on the Marketplace: if all versions were withdrawn, pin a different extension or handle the failure gracefully.","If behind a proxy, confirm the full JSON body is received (content-length vs actual bytes).","Cache the last-known-good vsixUrl so a temporary gallery gap does not break extension setup."],"exampleFix":"// before\nconst ext = await resolveExtension(id)\n\n// after\nasync function resolveWithRetry(id, attempts = 3) {\n  for (let i = 0; i < attempts; i++) {\n    try { return await resolveExtension(id) }\n    catch (e) {\n      if (!/no published versions/.test(e.message) || i === attempts - 1) throw e\n      await new Promise(r => setTimeout(r, 5_000 * (i + 1)))\n    }\n  }\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for (let attempt = 0; attempt < 3; attempt++) {\n  try {\n    return await resolveExtension(id)\n  } catch (e) {\n    const transient = e instanceof Error && e.message.includes('no published versions')\n    if (!transient || attempt === 2) throw e\n    await new Promise(r => setTimeout(r, 5_000 * (attempt + 1)))\n  }\n}","preventionTips":["Retry gallery lookups with backoff — empty version lists are usually transient gallery states.","Cache the last successful vsixUrl per extension id so setup survives short gallery outages.","Batch-install flows should collect per-extension failures and continue, then report a summary."],"tags":["marketplace","vscode","extension","transient"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}