{"record":{"id":"04753920f988dc4e","repo":"Budibase/budibase","slug":"github-release-not-found","errorCode":null,"errorMessage":"Github release not found","messagePattern":"Github release not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/api/controllers/plugin/github.ts","lineNumber":63,"sourceCode":"\n  const githubApiUrl = githubUrl.replace(\n    \"https://github.com/\",\n    \"https://api.github.com/repos/\"\n  )\n  const headers: Record<string, string> = token\n    ? { Authorization: `Bearer ${token}` }\n    : {}\n  const pluginDetails = await request(\n    githubApiUrl,\n    headers,\n    \"Repository not found\"\n  )\n  const pluginName = pluginDetails.name || name\n  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(","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/plugin/github.ts#L45-L81","documentation":"After fetching repo details, githubUpload derives the latest-release endpoint from the repo's releases_url template. If the API response has no releases_url field, the repo metadata is unexpected/incomplete and this error is thrown.","triggerScenarios":"The GitHub /repos/{owner}/{repo} response lacks the releases_url key — typically because the request did not actually return repo details (e.g. an error/proxy response parsed as JSON) or an unusual API-compatible host was used.","commonSituations":"Behind a proxy or mirror that alters GitHub API responses; using a non-github.com URL that was accepted after .git stripping but returns incomplete JSON; API schema changes.","solutions":["Confirm the repo URL resolves on api.github.com/repos/owner/repo and includes releases_url","Retry with the canonical https://github.com/owner/repo URL","Check any proxy/interceptor is not stripping GitHub API response fields","Check Budibase version and update if GitHub API schema changed"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const res = await fetch(`https://api.github.com/repos/${owner}/${repo}`)\nconst details = await res.json()\nif (!details.releases_url) throw new Error('Unexpected repo metadata: no releases_url')","typeGuard":"function hasReleasesUrl(d: unknown): d is { releases_url: string } {\n  return typeof d === 'object' && d !== null && 'releases_url' in d && typeof (d as any).releases_url === 'string'\n}","tryCatchPattern":"try {\n  await installPlugin({ source: 'GITHUB', url })\n} catch (err) {\n  if (err.message === 'Github release not found') {\n    console.error('GitHub API returned unexpected repo metadata — check proxy/API compatibility')\n  }\n}","preventionTips":["Use the canonical https://github.com/owner/repo URL so api.github.com responses are unmodified","Check proxies/enterprise gateways that rewrite api.github.com responses","Keep Budibase updated against GitHub API schema changes"],"tags":["github-api","plugin","missing-data"],"backgroundTag":"missing-github-release","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}