Flow-Launcher / Flow-Launcher/Flow.Launcher

BUG: Python plugin JSON output with non-ASCII text fails UTF-8 deserialization

Open
#4,570 1 comment 0 reactions 0 assignees View on GitHub
bug External Plugin Stale
Dominant language
C#
Stars
15.6k
Forks
644
Avg merge
16h 51m
Merged PRs (30d)
3

Description

### Description

Flow Launcher raised an unhandled exception while querying the third-party Python plugin **Forward Slash Path 1.1.0**. The first result's SubTitle contained non-ASCII text written by Python using the Windows console code page, while Flow Launcher attempted to deserialize the stream as UTF-8.

### Environment

- Flow Launcher version: 2.1.1
- OS Version: 26100.7623
- IntPtr Length: 8
- x64: True
- Python Path: C:\Users\eason\AppData\Local\Programs\Python\Python314\python.exe
- Node Path:
- Date: 07/12/2026 02:24:08
- Plugin: Forward Slash Path
- Plugin website: https://github.com/Flow-Launcher/Flow.Launcher
- Plugin author: Codex
- Plugin version: 1.1.0

### Exception

```text
System.Text.DecoderFallbackException: Unable to translate bytes [A1] at index 8 from specified code page to Unicode.
Source: System.Private.CoreLib
TargetAssembly: System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
TargetModule: System.Private.CoreLib.dll
TargetSite: Void Throw(Byte[], Int32)
at System.Text.DecoderExceptionFallbackBuffer.Throw(Byte[] bytesUnknown, Int32 index)
at System.Text.DecoderExceptionFallbackBuffer.Fallback(Byte[] bytesUnknown, Int32 index)
at System.Text.Encoding.GetCharCountWithFallback(ReadOnlySpan`1 bytes, Int32 originalBytesLength, DecoderNLS decoder)
at System.Text.Encoding.GetCharCountWithFallback(Byte* pBytesOriginal, Int32 originalByteCount, Int32 bytesConsumedSoFar)
at System.Text.Json.JsonReaderHelper.TranscodeHelper(ReadOnlySpan`1 utf8Unescaped)

System.InvalidOperationException: Cannot transcode invalid UTF-8 JSON text to UTF-16 string.
Source: System.Text.Json.Rethrowable
TargetAssembly: System.Text.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
TargetModule: System.Text.Json.dll
TargetSite: System.String TranscodeHelper(System.ReadOnlySpan`1[System.Byte])
at System.Text.Json.JsonReaderHelper.TranscodeHelper(ReadOnlySpan`1 utf8Unescaped)
at System.Text.Json.JsonReaderHelper.GetUnescapedString(ReadOnlySpan`1 utf8Source)
at System.Text.Json.Utf8JsonReader.GetString()
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonConverter`1.TryReadAsObject(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, Object& value)
at System.Text.Json.Serialization.Converters.LargeObjectWithParameterizedConstructorConverter`1.ReadAndCacheConstructorArgument(ReadStack& state, Utf8JsonReader& reader, JsonParameterInfo jsonParameterInfo)
at System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1.ReadConstructorArgumentsWithContinuation(ReadStack& state, Utf8JsonReader& reader, JsonSerializerOptions options)
at System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)

System.Text.Json.JsonException: The JSON value could not be converted to System.String. Path: $.result[0].SubTitle | LineNumber: 0 | BytePositionInLine: 99.
Source: System.Text.Json
TargetAssembly: System.Text.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
TargetModule: System.Text.Json.dll
TargetSite: Void ReThrowWithPath(System.Text.Json.ReadStack ByRef, System.Text.Json.Utf8JsonReader ByRef, System.Exception)
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, Utf8JsonReader& reader, Exception ex)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.ContinueDeserialize(ReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, T& value)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.DeserializeAsync(Stream utf8Json, CancellationToken cancellationToken)
at Flow.Launcher.Core.Plugin.JsonRPCPlugin.DeserializedResultAsync(Stream output) in C:\projects\flow-launcher\Flow.Launcher.Core\Plugin\JsonRPCPlugin.cs:line 63
at Flow.Launcher.Core.Plugin.JsonRPCPlugin.DeserializedResultAsync(Stream output) in C:\projects\flow-launcher\Flow.Launcher.Core\Plugin\JsonRPCPlugin.cs:line 66
at Flow.Launcher.Core.Plugin.JsonRPCPlugin.QueryAsync(Query query, CancellationToken token) in C:\projects\flow-launcher\Flow.Launcher.Core\Plugin\JsonRPCPlugin.cs:line 240
at Flow.Launcher.Core.Plugin.PluginManager.<>c__DisplayClass32_0.<b__1>d.MoveNext() in C:\projects\flow-launcher\Flow.Launcher.Core\Plugin\PluginManager.cs:line 423
--- End of stack trace from previous location ---
at Flow.Launcher.Infrastructure.Stopwatch.DebugAsync(String className, String message, Func`1 action, String methodName) in C:\projects\flow-launcher\Flow.Launcher.Infrastructure\Stopwatch.cs:line 31
at Flow.Launcher.Core.Plugin.PluginManager.QueryForPluginAsync(PluginPair pair, Query query, CancellationToken token) in C:\projects\flow-launcher\Flow.Launcher.Core\Plugin\PluginManager.cs:line 422

Flow.Launcher.Core.ExternalPlugins.FlowPluginException: The JSON value could not be converted to System.String. Path: $.result[0].SubTitle | LineNumber: 0 | BytePositionInLine: 99.
Source: Flow.Launcher.Core
TargetAssembly: Flow.Launcher.Core, Version=2.1.1.0, Culture=neutral, PublicKeyToken=null
TargetModule: Flow.Launcher.Core.dll
TargetSite: Boolean b__2(Flow.Launcher.Plugin.ActionContext)
at Flow.Launcher.Core.Plugin.PluginManager.<>c__DisplayClass32_1.b__2(ActionContext _) in C:\projects\flow-launcher\Flow.Launcher.Core\Plugin\PluginManager.cs:line 452
at Flow.Launcher.Plugin.Result.ExecuteAsync(ActionContext context) in /_/Flow.Launcher.Plugin/Result.cs:line 281
at Flow.Launcher.ViewModel.MainViewModel.OpenResultAsync(String index) in C:\projects\flow-launcher\Flow.Launcher\ViewModel\MainViewModel.cs:line 520
at CommunityToolkit.Mvvm.Input.AsyncRelayCommand.AwaitAndThrowIfFailed(Task executionTask)
at System.Threading.Tasks.Task.<>c.b__128_0(Object state)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
```

### Log file

[Flow.Launcher.2026-07-12.log](https://gist.githubusercontent.com/Easonoi/b965fa25838963959e6dd733ac09c827/raw/a97a409f749ac503713c86a53217782d83738856/Flow.Launcher.2026-07-12.log) (full log uploaded to GitHub as a secret gist)

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs, especially DeserializedResultAsync(Stream output) at the stack-trace locations around lines 63 and 66. Reproduce the query with the Forward Slash Path plugin or equivalent non-ASCII Python output, then verify that the result JSON deserializes without an unhandled exception and preserves the SubTitle text.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, desktop
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.