{"record":{"id":"575e1c0419cb4fb7","repo":"Flow-Launcher/Flow.Launcher","slug":"json-rpc-plugin-error-stream-output","errorCode":null,"errorMessage":"<JSON-RPC plugin error stream output>","messagePattern":"<JSON-RPC plugin error stream output>","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs","lineNumber":74,"sourceCode":"        }\n\n        public override async Task InitAsync(PluginInitContext context)\n        {\n            await base.InitAsync(context);\n\n            SetupJsonRPC();\n\n            _ = ReadErrorAsync();\n\n            await RPC.InvokeAsync(\"initialize\", context);\n\n            async Task ReadErrorAsync()\n            {\n                var error = await ErrorStream.ReadToEndAsync();\n\n                if (!string.IsNullOrEmpty(error))\n                {\n                    throw new Exception(error);\n                }\n            }\n        }\n\n        public event ResultUpdatedEventHandler ResultsUpdated;\n\n        protected enum MessageHandlerType\n        {\n            HeaderDelimited,\n            LengthHeaderDelimited,\n            NewLineDelimited\n        }\n\n        protected abstract MessageHandlerType MessageHandler { get; }\n\n        private void SetupJsonRPC()\n        {\n            var formatter = new SystemTextJsonFormatter { JsonSerializerOptions = RequestSerializeOption };","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/Flow-Launcher/Flow.Launcher/blob/7fc63b07bbaa10a0f0b2601487913fcba9ed24b0/Flow.Launcher.Core/Plugin/JsonRPCPluginV2.cs#L56-L92","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the message — it is the plugin process's verbatim stderr and identifies the failing component.","Run the plugin executable directly with the same args/env Flow Launcher uses and observe its stderr.","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.","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.","Reinstall or update the plugin."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null","typeGuard":"null","tryCatchPattern":"// ReadErrorAsync is fire-and-forget — wrap InitAsync and observe the detached task\ntry { await plugin.InitAsync(context); }\ncatch (Exception ex) { Context.API.LogException(ClassName, $\"V2 plugin init failed: {ex.Message}\", ex); }","preventionTips":["Because ReadErrorAsync is detached, attach an exception handler: _ = ReadErrorAsync().ContinueWith(t => Log(...), TaskContinuationOptions.OnlyOnFaulted).","Keep V2 plugin stderr clean — route logs to a file.","Verify the plugin's declared APIVersion matches the V2 protocol before load.","Monitor Flow Launcher's unobserved-task-exception logs for hidden V2 init failures."],"tags":["json-rpc","plugin","subprocess","stderr","v2-plugin","fire-and-forget"],"backgroundTag":null,"analyzedSha":"7fc63b07bbaa10a0f0b2601487913fcba9ed24b0","analyzedAt":"2026-08-13T14:54:20.914Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}