{"record":{"id":"8262d9c686d8fea1","repo":"Budibase/budibase","slug":"github-latest-release-url-not-found","errorCode":null,"errorMessage":"Github latest release url not found","messagePattern":"Github latest release url not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/api/controllers/plugin/github.ts","lineNumber":77,"sourceCode":"  const pluginLatestReleaseUrl = pluginDetails?.[\"releases_url\"]\n    ? pluginDetails?.[\"releases_url\"].replace(\"{/id}\", \"/latest\")\n    : undefined\n  if (!pluginLatestReleaseUrl) {\n    throw new Error(\"Github release not found\")\n  }\n\n  const pluginReleaseDetails = await request(\n    pluginLatestReleaseUrl,\n    headers,\n    \"Github latest release not found\"\n  )\n  const pluginReleaseTarballAsset = pluginReleaseDetails?.assets?.find(\n    (x: any) => x?.[\"content_type\"] === \"application/gzip\"\n  )\n  const pluginLastReleaseTarballUrl =\n    pluginReleaseTarballAsset?.[\"browser_download_url\"]\n  if (!pluginLastReleaseTarballUrl) {\n    throw new Error(\"Github latest release url not found\")\n  }\n\n  try {\n    path = await downloadUnzipTarball(\n      pluginLastReleaseTarballUrl,\n      pluginName,\n      headers\n    )\n    return await getPluginMetadata(path)\n  } catch (err: any) {\n    if (path) {\n      deleteFolderFileSystem(path)\n    }\n    let errMsg = err?.message || err\n    if (errMsg === \"unexpected response Not Found\") {\n      errMsg = \"Github release tarball not found\"\n    }\n    throw new Error(errMsg)","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/plugin/github.ts#L59-L95","documentation":"The latest GitHub release must contain a downloadable asset whose content_type is application/gzip; its browser_download_url is used as the plugin tarball. If no such asset exists, the release cannot be downloaded and this error is thrown.","triggerScenarios":"The repo's latest GitHub release has no .tar.gz asset (only source zip / wrong content_type), or the release has zero assets.","commonSituations":"Plugin repo publishes releases via GitHub auto-generated source archives only (GitHub source zips get application/zip content_type); CI uploaded a zip instead of tar.gz; repo has a tag but no packaged release.","solutions":["Ask the plugin maintainer to attach a .tar.gz (application/gzip) asset to the latest release","Publish a new release including a tar.gz build artifact","Check the release assets at https://github.com/owner/repo/releases/latest and confirm a gzip asset is present","Point at an older release/tag that does include a tar.gz if the flow allows"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const rel = await fetch(`https://api.github.com/repos/${owner}/${repo}/releases/latest`).then(r => r.json())\nconst hasGzip = (rel.assets || []).some(a => a.content_type === 'application/gzip')\nif (!hasGzip) throw new Error('Latest release has no tar.gz asset')","typeGuard":"function hasGzipAsset(release: { assets?: Array<{ content_type?: string }> }): boolean {\n  return (release.assets ?? []).some(a => a.content_type === 'application/gzip')\n}","tryCatchPattern":"try {\n  await installPlugin({ source: 'GITHUB', url })\n} catch (err) {\n  if (err.message === 'Github latest release url not found') {\n    console.error('Ask the maintainer to attach a .tar.gz asset to the latest release')\n  }\n}","preventionTips":["As a plugin author, always attach a .tar.gz build artifact to every release","Remember GitHub source archives report application/zip and do not count","Check the release assets page before attempting installation"],"tags":["github-api","plugin","release-artifacts"],"backgroundTag":"missing-github-release","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}