Flow-Launcher/Flow.Launcher · error · InvalidDataException
<JSON-RPC plugin process stderr>
Error message
<JSON-RPC plugin process stderr>
What it means
Thrown as InvalidDataException carrying the raw UTF-8 stderr of the child JSON-RPC plugin process. The v1 JsonRPCPlugin captures the plugin executable's stdout and stderr into separate buffers via CopyToAsync, and when the process exits with a non-empty errorBuffer (case (_, not 0)), the buffered stderr text is re-thrown. This is the primary channel through which a misbehaving/buggy plugin process surfaces its crash message to Flow Launcher's host.
Source
Thrown at Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs:220
// token expire won't instantly trigger the exception,
// manually kill process at before
await process.WaitForExitAsync(token);
await Task.WhenAll(sourceCopyTask, errorCopyTask);
}
catch (OperationCanceledException)
{
await sourceBuffer.DisposeAsync();
return Stream.Null;
}
switch (sourceBuffer.Length, errorBuffer.Length)
{
case (0, 0):
const string errorMessage = "Empty JSON-RPC Response.";
Context.API.LogWarn(ClassName, errorMessage);
break;
case (_, not 0):
throw new InvalidDataException(Encoding.UTF8.GetString(errorBuffer.ToArray())); // The process has exited with an error message
}
sourceBuffer.Seek(0, SeekOrigin.Begin);
return sourceBuffer;
}
public override async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
{
var request = new JsonRPCRequestModel(RequestId++,
"query",
new object[]
{
query.Search
},
Settings?.Inner);
var output = await RequestAsync(request, token);View on GitHub (pinned to 7fc63b07bb)
Solutions
- Read the message text — it IS the plugin's stderr output, so it names the actual failing module/line in the plugin.
- Verify the plugin's declared executable and runtime exist (e.g. python.exe on PATH, node version) by running the plugin's command manually.
- Check the plugin's WorkingDirectory and language interpreter config in its plugin.json.
- If the plugin intentionally logs non-fatal diagnostics to stderr, this v1 host cannot distinguish them from fatal errors — switch the plugin to the V2 protocol or have it write logs to a file instead.
- Update or reinstall the offending plugin from the plugin manifest.
Example fix
// before (plugin v1 — any stderr is fatal)
import sys
print('loading model...', file=sys.stderr) // triggers the throw
// after — keep stderr clean, log to a file
import logging
logging.basicConfig(filename='plugin.log')
logging.info('loading model...') Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the plugin executable and runtime before invoking
var psi = new ProcessStartInfo(pluginExecutable) { RedirectStandardError = true };
if (!File.Exists(psi.FileName)) return; // guard before RequestAsync Type guard
null
Try / catch
try { var results = await plugin.QueryAsync(query, token); }
catch (InvalidDataException ex) when (ex.Message.Contains("JSON-RPC"))
{
Context.API.LogException(ClassName, $"Plugin {plugin.Name} stderr: {ex.Message}", ex);
return new List<Result>(); // graceful empty results
} Prevention
- Treat the plugin's stderr as fatal in v1 — ensure plugins log diagnostics to a file, not stderr.
- Pin plugin runtime versions in plugin.json and verify they are installed.
- Smoke-test plugins by running their executable directly before enabling them.
- Set a query timeout via the CancellationToken so a hung plugin process is killed.
When it happens
Trigger: The plugin child process writes anything to stderr before or while exiting (an uncaught exception, a Python traceback, a Node stack trace, a failed assertion). Specifically: sourceBuffer.Length is anything AND errorBuffer.Length is not 0 after process.WaitForExitAsync completes. This includes the case where the plugin wrote both valid stdout and an error to stderr — error wins.
Common situations: Plugin written in Python/Node/Go crashes on startup (missing dependency, wrong runtime version); plugin throws an unhandled exception during query handling that gets dumped to stderr; plugin executable path points to a binary whose required runtime is not installed; plugin logs a warning to stderr then continues (this would still throw even though the plugin is otherwise healthy, since v1 treats any stderr as fatal).
Related errors
AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13).
Data as JSON: /api/errors/70c5eefdd054ea2a.
Report an issue: GitHub.