Flow-Launcher/Flow.Launcher · error · Exception

<JSON-RPC plugin error stream output>

Error message

<JSON-RPC plugin error stream output>

What it means

Thrown as a plain Exception whose message is the entire stderr of the V2 JSON-RPC plugin process, read to end during InitAsync. Unlike v1, the read is fire-and-forget (_ = ReadErrorAsync()) so the throw happens on a detached task — it will surface as an unobserved task exception / may not propagate cleanly to the caller of InitAsync. V2 plugins use StreamJsonRpc over stdin/stdout pipes, and stderr is reserved exclusively for fatal diagnostics.

Source

Thrown at Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs:74

        }

        public override async Task InitAsync(PluginInitContext context)
        {
            await base.InitAsync(context);

            SetupJsonRPC();

            _ = ReadErrorAsync();

            await RPC.InvokeAsync("initialize", context);

            async Task ReadErrorAsync()
            {
                var error = await ErrorStream.ReadToEndAsync();

                if (!string.IsNullOrEmpty(error))
                {
                    throw new Exception(error);
                }
            }
        }

        public event ResultUpdatedEventHandler ResultsUpdated;

        protected enum MessageHandlerType
        {
            HeaderDelimited,
            LengthHeaderDelimited,
            NewLineDelimited
        }

        protected abstract MessageHandlerType MessageHandler { get; }

        private void SetupJsonRPC()
        {
            var formatter = new SystemTextJsonFormatter { JsonSerializerOptions = RequestSerializeOption };

View on GitHub (pinned to 7fc63b07bb)

Solutions

  1. Read the message — it is the plugin process's verbatim stderr and identifies the failing component.
  2. Run the plugin executable directly with the same args/env Flow Launcher uses and observe its stderr.
  3. Confirm the plugin declares APIVersion >= 2 in plugin.json and actually speaks the V2 framed protocol, otherwise stderr noise from a v1-style plugin will trip this.
  4. Because ReadErrorAsync is fire-and-forget, the exception may not bubble to the UI — check Flow Launcher's logs/UnobservedTaskException handler for the real message.
  5. Reinstall or update the plugin.
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

// ReadErrorAsync is fire-and-forget — wrap InitAsync and observe the detached task
try { await plugin.InitAsync(context); }
catch (Exception ex) { Context.API.LogException(ClassName, $"V2 plugin init failed: {ex.Message}", ex); }

Prevention

When it happens

Trigger: The V2 plugin process writes any non-empty string to its ErrorStream during the lifetime of InitAsync (which spans the initialize RPC call). The throw fires after ErrorStream.ReadToEndAsync completes, i.e. when the pipe closes (process exit) or EOF is reached.

Common situations: V2 plugin runtime missing or wrong version; plugin crashes during its initialize handler and dumps a stack trace to stderr; a native dependency of the plugin fails to load and writes to stderr before the RPC handshake completes; mixing a debug build that prints to stderr.

Related errors


AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13). Data as JSON: /api/errors/575e1c0419cb4fb7. Report an issue: GitHub.