{"record":{"id":"39fe27511eff9453","repo":"nextlevelbuilder/ui-ux-pro-max-skill","slug":"no-zip-asset-found-in-latest-release","errorCode":null,"errorMessage":"No ZIP asset found in latest release","messagePattern":"No ZIP asset found in latest release","errorType":"exception","errorClass":"GitHubDownloadError","httpStatus":null,"severity":"error","filePath":"cli/src/commands/init.ts","lineNumber":58,"sourceCode":"/**\n * Try to install from GitHub release (legacy method)\n * Returns the copied folders if successful, null if failed\n */\nasync function tryGitHubInstall(\n  targetDir: string,\n  aiType: AIType,\n  spinner: ReturnType<typeof ora>,\n  token?: string\n): Promise<string[] | null> {\n  let tempDir: string | null = null;\n\n  try {\n    spinner.text = 'Fetching latest release from GitHub...';\n    const release = await getLatestRelease(token);\n    const assetUrl = getAssetUrl(release);\n\n    if (!assetUrl) {\n      throw new GitHubDownloadError('No ZIP asset found in latest release');\n    }\n\n    spinner.text = `Downloading ${release.tag_name}...`;\n    tempDir = await createTempDir();\n    const zipPath = join(tempDir, 'release.zip');\n\n    await downloadRelease(assetUrl, zipPath, token);\n\n    spinner.text = 'Extracting and installing files...';\n    const { copiedFolders, tempDir: extractedTempDir } = await installFromZip(\n      zipPath,\n      targetDir,\n      aiType\n    );\n\n    // Cleanup temp directory\n    await cleanup(extractedTempDir);\n","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/nextlevelbuilder/ui-ux-pro-max-skill/blob/a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5/cli/src/commands/init.ts#L40-L76","documentation":"Thrown by the uipro CLI installer when the GitHub 'latest release' it fetched contains no asset whose name ends in .zip. The installer resolves the release via getLatestRelease(), then getAssetUrl() scans release.assets for a .zip upload (browser_download_url); if none exists, installFromGitHub() aborts with GitHubDownloadError. It means the release exists but was published without the expected ZIP artifact.","triggerScenarios":"Running `uipro init` when the latest GitHub release was created from a tag without attaching a ZIP asset, when the release is a draft/nightly that only uploads e.g. tar.gz artifacts, or when asset names were changed in the release workflow so the `.endsWith('.zip')` check in getAssetUrl() no longer matches.","commonSituations":"Maintainer cuts a release from a tag without running the asset-packaging workflow; CI artifact upload step failed silently so the release published anyway; a release pipeline switched to .tar.gz; querying GitHub with a token that lacks access so the assets array comes back empty for a private repo.","solutions":["Check the latest release on the repo's GitHub Releases page and confirm a .zip asset is attached; re-run the release packaging workflow if not.","If you maintain the repo, ensure the release workflow uploads the zip asset before marking the release 'latest'.","If the asset uses a different extension intentionally, extend getAssetUrl() in cli/src/utils/github.ts to accept it.","As a workaround, use the CLI's local/bundled install path instead of the GitHub download, or pin to an older release that has the asset."],"exampleFix":"// before (github.ts)\nconst asset = release.assets.find(a => a.name.endsWith('.zip'));\n// after: also surface a clearer error and accept tar.gz\nconst asset = release.assets.find(a => /\\.(zip|tar\\.gz)$/.test(a.name));\nif (!asset) {\n  throw new GitHubDownloadError(\n    `No ZIP asset found in latest release (assets: ${release.assets.map(a => a.name).join(', ') || 'none'})`\n  );\n}","handlingStrategy":"validation","validationCode":"import { getLatestRelease, getAssetUrl } from './utils/github';\n\nasync function assertReleaseHasZip(token?: string) {\n  const release = await getLatestRelease(token);\n  const url = getAssetUrl(release);\n  if (!url) {\n    throw new Error(\n      `Release ${release.tag_name} has no zip asset (assets: ${release.assets.map(a => a.name).join(', ') || 'none'})`\n    );\n  }\n  return { release, url };\n}","typeGuard":null,"tryCatchPattern":"try {\n  await installFromGitHub(targetDir, aiType, spinner, token);\n} catch (e) {\n  if (e instanceof GitHubDownloadError && /No ZIP asset/.test(e.message)) {\n    // fall back to the CLI's bundled local assets instead of the GitHub download\n    await installFromLocalAssets(targetDir, aiType, spinner);\n  } else throw e;\n}","preventionTips":["Make the release workflow fail if the zip asset upload step fails, so 'latest' never ships without the artifact.","Log the release.assets names in telemetry when this error fires to make diagnosis one-step.","Keep the CLI's local-assets install path as a fallback for GitHub release anomalies."],"tags":["cli","github-api","release-assets","installer"],"backgroundTag":null,"analyzedSha":"a38d04c3d5c298c851dbe5e6ee1965ee3de42cb5","analyzedAt":"2026-08-14T18:51:02.321Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}