{"record":{"id":"7360c3e4a2d8c46b","repo":"SubtitleEdit/subtitleedit","slug":"plugin-entry-name-has-no-download-for-this-pla","errorCode":null,"errorMessage":"Plugin '{entry.Name}' has no download for this platform ({PluginPlatform.GetCurrentKey() ?? \"unknown\"}).","messagePattern":"Plugin '(.+?)' has no download for this platform \\((.+?)\\)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/ui/Logic/Plugins/PluginDownloadService.cs","lineNumber":39,"sourceCode":"    {\n        _httpClient = httpClient;\n        _zipUnpacker = zipUnpacker;\n        _pluginCatalog = pluginCatalog;\n    }\n\n    public async Task<PluginIndex> GetIndexAsync(CancellationToken cancellationToken)\n    {\n        await using var stream = await _httpClient.GetStreamAsync(PluginConstants.OnlineIndexUrl, cancellationToken);\n        var index = await JsonSerializer.DeserializeAsync(stream, PluginJsonContext.Default.PluginIndex, cancellationToken);\n        return index ?? new PluginIndex();\n    }\n\n    public async Task InstallAsync(PluginIndexEntry entry, IProgress<float>? progress, CancellationToken cancellationToken)\n    {\n        var downloadUrl = PluginPlatform.ResolveDownloadUrl(entry);\n        if (string.IsNullOrWhiteSpace(downloadUrl))\n        {\n            throw new InvalidOperationException($\"Plugin '{entry.Name}' has no download for this platform ({PluginPlatform.GetCurrentKey() ?? \"unknown\"}).\");\n        }\n\n        Directory.CreateDirectory(Se.PluginsFolder);\n\n        // Unpack into a temp folder inside the plugins folder so the final move stays on the same volume.\n        var tempDirectory = Path.Combine(Se.PluginsFolder, \".tmp-\" + Guid.NewGuid().ToString(\"N\"));\n        try\n        {\n            Directory.CreateDirectory(tempDirectory);\n\n            using var zipStream = new MemoryStream();\n            await DownloadHelper.DownloadFileAsync(_httpClient, downloadUrl, zipStream, progress, cancellationToken);\n            cancellationToken.ThrowIfCancellationRequested();\n\n            // Unzip and the subsequent file moves are synchronous; running them on a worker\n            // thread keeps the UI responsive (notably for the cancel-download button) and lets\n            // ThrowIfCancellationRequested between phases stop work as soon as the user reacts.\n            await Task.Run(() =>","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/ui/Logic/Plugins/PluginDownloadService.cs#L21-L57","documentation":"InvalidOperationException raised when PluginPlatform.ResolveDownloadUrl returns null/empty for the current OS+architecture key (e.g. win-x64). Resolution fails if the entry's Downloads map is empty, the current platform key itself is null (unsupported OS/arch), or no key in the map matches the runtime.","triggerScenarios":"InstallAsync is invoked for a PluginIndexEntry whose Downloads has no entry for the current RID. GetCurrentKey() returns null on an unsupported OS or an architecture outside x64/arm64/x86/arm, or the entry only ships other platforms (e.g. win-x64 only while the user runs linux-arm64).","commonSituations":"ARM Linux or Apple Silicon users, plugins authored for Windows only, a stale plugin index missing the user's architecture, or a malformed Downloads map.","solutions":["Call PluginPlatform.IsSupportedByEntry(entry) before offering/starting install and hide unsupported entries in the UI.","Choose a plugin variant whose Downloads map lists the user's platform key.","If authoring a plugin, publish zips for win-x64, linux-x64, linux-arm64, osx-x64, and osx-arm64.","Refresh the plugin index (GetIndexAsync) in case a newer entry adds the missing platform."],"exampleFix":"// before\nawait _pluginDownloadService.InstallAsync(entry, progress, ct);\n\n// after\nif (!PluginPlatform.IsSupportedByEntry(entry))\n{\n    ShowUser($\"{entry.Name} is not available for {PluginPlatform.GetCurrentKey() ?? \"this platform\"}.\", isError: true);\n    return;\n}\nawait _pluginDownloadService.InstallAsync(entry, progress, ct);","handlingStrategy":"validation","validationCode":"if (!PluginPlatform.IsSupportedByEntry(entry))\n{\n    Console.WriteLine($\"{entry.Name} unavailable for {PluginPlatform.GetCurrentKey() ?? \"this platform\"}\");\n    return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call PluginPlatform.IsSupportedByEntry before offering install.","Filter the plugin list by the current platform key in the UI.","When authoring plugins, publish zips for all supported RIDs.","Refresh the plugin index so newly added platforms appear."],"tags":["plugins","platform","runtime","distribution","rid"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}