SubtitleEdit/subtitleedit · error · InvalidOperationException

Plugin '{entry.Name}' has no download for this platform ({Pl

Error message

Plugin '{entry.Name}' has no download for this platform ({PluginPlatform.GetCurrentKey() ?? "unknown"}).

What it means

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.

Source

Thrown at src/ui/Logic/Plugins/PluginDownloadService.cs:39

    {
        _httpClient = httpClient;
        _zipUnpacker = zipUnpacker;
        _pluginCatalog = pluginCatalog;
    }

    public async Task<PluginIndex> GetIndexAsync(CancellationToken cancellationToken)
    {
        await using var stream = await _httpClient.GetStreamAsync(PluginConstants.OnlineIndexUrl, cancellationToken);
        var index = await JsonSerializer.DeserializeAsync(stream, PluginJsonContext.Default.PluginIndex, cancellationToken);
        return index ?? new PluginIndex();
    }

    public async Task InstallAsync(PluginIndexEntry entry, IProgress<float>? progress, CancellationToken cancellationToken)
    {
        var downloadUrl = PluginPlatform.ResolveDownloadUrl(entry);
        if (string.IsNullOrWhiteSpace(downloadUrl))
        {
            throw new InvalidOperationException($"Plugin '{entry.Name}' has no download for this platform ({PluginPlatform.GetCurrentKey() ?? "unknown"}).");
        }

        Directory.CreateDirectory(Se.PluginsFolder);

        // Unpack into a temp folder inside the plugins folder so the final move stays on the same volume.
        var tempDirectory = Path.Combine(Se.PluginsFolder, ".tmp-" + Guid.NewGuid().ToString("N"));
        try
        {
            Directory.CreateDirectory(tempDirectory);

            using var zipStream = new MemoryStream();
            await DownloadHelper.DownloadFileAsync(_httpClient, downloadUrl, zipStream, progress, cancellationToken);
            cancellationToken.ThrowIfCancellationRequested();

            // Unzip and the subsequent file moves are synchronous; running them on a worker
            // thread keeps the UI responsive (notably for the cancel-download button) and lets
            // ThrowIfCancellationRequested between phases stop work as soon as the user reacts.
            await Task.Run(() =>

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Call PluginPlatform.IsSupportedByEntry(entry) before offering/starting install and hide unsupported entries in the UI.
  2. Choose a plugin variant whose Downloads map lists the user's platform key.
  3. If authoring a plugin, publish zips for win-x64, linux-x64, linux-arm64, osx-x64, and osx-arm64.
  4. Refresh the plugin index (GetIndexAsync) in case a newer entry adds the missing platform.

Example fix

// before
await _pluginDownloadService.InstallAsync(entry, progress, ct);

// after
if (!PluginPlatform.IsSupportedByEntry(entry))
{
    ShowUser($"{entry.Name} is not available for {PluginPlatform.GetCurrentKey() ?? "this platform"}.", isError: true);
    return;
}
await _pluginDownloadService.InstallAsync(entry, progress, ct);
Defensive patterns

Strategy: validation

Validate before calling

if (!PluginPlatform.IsSupportedByEntry(entry))
{
    Console.WriteLine($"{entry.Name} unavailable for {PluginPlatform.GetCurrentKey() ?? "this platform"}");
    return;
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/7360c3e4a2d8c46b. Report an issue: GitHub.