{"record":{"id":"c34fee434561a20e","repo":"LykosAI/StabilityMatrix","slug":"no-download-url-available","errorCode":null,"errorMessage":"No download URL available","messagePattern":"No download URL available","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs","lineNumber":67,"sourceCode":"\n    protected string GetDownloadUrl(DownloadPackageVersionOptions versionOptions)\n    {\n        if (!string.IsNullOrWhiteSpace(versionOptions.CommitHash))\n        {\n            return $\"https://github.com/{RepositoryAuthor}/{RepositoryName}/archive/{versionOptions.CommitHash}.zip\";\n        }\n\n        if (!string.IsNullOrWhiteSpace(versionOptions.VersionTag))\n        {\n            return $\"https://api.github.com/repos/{RepositoryAuthor}/{RepositoryName}/zipball/{versionOptions.VersionTag}\";\n        }\n\n        if (!string.IsNullOrWhiteSpace(versionOptions.BranchName))\n        {\n            return $\"https://api.github.com/repos/{RepositoryAuthor}/{RepositoryName}/zipball/{versionOptions.BranchName}\";\n        }\n\n        throw new Exception(\"No download URL available\");\n    }\n\n    protected BaseGitPackage(\n        IGithubApiCache githubApi,\n        ISettingsManager settingsManager,\n        IDownloadService downloadService,\n        IPrerequisiteHelper prerequisiteHelper,\n        IPyInstallationManager pyInstallationManager,\n        IPipWheelService pipWheelService\n    )\n        : base(settingsManager)\n    {\n        GithubApi = githubApi;\n        DownloadService = downloadService;\n        PrerequisiteHelper = prerequisiteHelper;\n        PyInstallationManager = pyInstallationManager;\n        PipWheelService = pipWheelService;\n    }","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/LykosAI/StabilityMatrix/blob/af93d6ef57c01cd890d7e0ad0a9ea8c9fcda3002/StabilityMatrix.Core/Models/Packages/BaseGitPackage.cs#L49-L85","documentation":"BaseGitPackage.GetDownloadUrl builds a download URL from the selected VersionOptions. If the version has a BranchName it returns the GitHub zipball URL, but when no branch, tag, or release-derived URL could be constructed it throws a generic Exception(\"No download URL available\"). The library throws it because the resolved version points at neither a release asset nor a branch, so there is no determinate archive to download.","triggerScenarios":"Calling DownloadPackage/Install with VersionOptions whose BranchName is null/whitespace and which also lacks a usable tag or release reference — e.g. passing a default-constructed VersionOptions, a version pointing at a commit hash the URL builder does not handle, or a repository where the selected release was deleted so no asset/zipball URL resolves.","commonSituations":"A pinned package version was removed by the upstream repo (release or tag deleted), leaving VersionOptions with no branch; a config/workspace JSON was hand-edited and the version fields were dropped or blanked; a fork was swapped in whose release/branch layout does not match what the package class expects.","solutions":["Set VersionOptions.BranchName (or re-select a valid release/tag version in the UI) so the zipball URL can be built, e.g. versionOptions = new VersionOptions { BranchName = \"master\" }.","Refresh the package's available versions via the GitHub API and choose an existing release; the previously selected one no longer exists upstream.","If VersionOptions came from stored config/workspace data, correct the JSON so version fields (tag/branch) are populated.","Verify RepositoryAuthor/RepositoryName point at a real, accessible repo (renamed/moved repos break version resolution)."],"exampleFix":"// before\nvar options = new InstallPackageOptions { VersionOptions = new VersionOptions() };\nawait package.InstallPackage(options, progress); // Exception: No download URL available\n\n// after\nvar options = new InstallPackageOptions\n{\n    VersionOptions = new VersionOptions { BranchName = \"master\" }\n};\nawait package.InstallPackage(options, progress); // builds .../zipball/master","handlingStrategy":"validation","validationCode":"if (versionOptions is null ||\n    string.IsNullOrWhiteSpace(versionOptions.BranchName) &&\n    string.IsNullOrWhiteSpace(versionOptions.TagName) &&\n    versionOptions.Version is null)\n{\n    throw new ArgumentException(\"VersionOptions must specify a branch, tag, or release version before install.\");\n}","typeGuard":"bool HasResolvableVersion(VersionOptions? v) =>\n    v is not null &&\n    (!string.IsNullOrWhiteSpace(v.BranchName) || !string.IsNullOrWhiteSpace(v.TagName) || v.Version is not null);","tryCatchPattern":"try\n{\n    await package.InstallPackage(options, progress, ct);\n}\ncatch (Exception ex) when (ex.Message == \"No download URL available\")\n{\n    logger.LogError(ex, \"Version {Version} of {Repo} has no downloadable archive; re-selecting latest release\",\n        options.VersionOptions, package.RepositoryName);\n    options.VersionOptions = await package.GetLatestVersionAsync(ct); // refresh and retry\n}","preventionTips":["Always populate VersionOptions from a freshly queried version list (GitHub API) instead of hand-written or stale config values.","Handle upstream release/tag deletion by refreshing available versions when an install fails.","When persisting workspace config, validate that version fields survive serialization round-trips."],"tags":["git","github","download-url","version-options","configuration"],"backgroundTag":"missing-required-config-field","analyzedSha":"af93d6ef57c01cd890d7e0ad0a9ea8c9fcda3002","analyzedAt":"2026-09-12T19:02:43.389Z","contentChangedAt":"2026-09-12T19:02:43.389Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}