[pigeon] Fix async handling in C++ generator (#3040)

* Add unit test

* Switch all errors to direct return

* Make 'wrapped' entirely local

* Switch reply to copy instead of reference

* Version bump
diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md
index 2af2032..1c47219 100644
--- a/packages/pigeon/CHANGELOG.md
+++ b/packages/pigeon/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 5.0.1
+
+* [c++] Fixes undefined behavior in `@async` methods.
+
 ## 5.0.0
 
 * Creates new Generator classes for each language.
diff --git a/packages/pigeon/lib/cpp_generator.dart b/packages/pigeon/lib/cpp_generator.dart
index cddefac..ae5f912 100644
--- a/packages/pigeon/lib/cpp_generator.dart
+++ b/packages/pigeon/lib/cpp_generator.dart
@@ -498,9 +498,9 @@
       indent.writeln(
           'static void SetUp(flutter::BinaryMessenger* binary_messenger, ${api.name}* api);');
       indent.writeln(
-          'static flutter::EncodableList WrapError(std::string_view error_message);');
+          'static flutter::EncodableValue WrapError(std::string_view error_message);');
       indent.writeln(
-          'static flutter::EncodableList WrapError(const FlutterError& error);');
+          'static flutter::EncodableValue WrapError(const FlutterError& error);');
     });
     indent.scoped(' protected:', '', () {
       indent.writeln('${api.name}() = default;');
@@ -541,7 +541,6 @@
           indent.write(
               'channel->SetMessageHandler([api](const flutter::EncodableValue& message, const flutter::MessageReply<flutter::EncodableValue>& reply) ');
           indent.scoped('{', '});', () {
-            indent.writeln('flutter::EncodableList wrapped;');
             indent.write('try ');
             indent.scoped('{', '}', () {
               final List<String> methodArgument = <String>[];
@@ -627,7 +626,7 @@
                     indent.write('if ($encodableArgName.IsNull()) ');
                     indent.scoped('{', '}', () {
                       indent.writeln(
-                          'reply(flutter::EncodableValue(WrapError("$argName unexpectedly null.")));');
+                          'reply(WrapError("$argName unexpectedly null."));');
                       indent.writeln('return;');
                     });
                   }
@@ -637,17 +636,16 @@
                 });
               }
 
-              String wrapResponse(String reply, TypeDeclaration returnType) {
-                String elseBody = '';
-                final String ifCondition;
+              String wrapResponse(TypeDeclaration returnType,
+                  {String prefix = ''}) {
+                final String nonErrorPath;
+                final String errorCondition;
                 final String errorGetter;
-                final String prefix = (reply != '') ? '\t' : '';
-
                 const String nullValue = 'flutter::EncodableValue()';
+
                 if (returnType.isVoid) {
-                  elseBody =
-                      '$prefix\twrapped.push_back($nullValue);${indent.newline}';
-                  ifCondition = 'output.has_value()';
+                  nonErrorPath = '${prefix}wrapped.push_back($nullValue);';
+                  errorCondition = 'output.has_value()';
                   errorGetter = 'value';
                 } else {
                   final HostDatatype hostType = getHostDatatype(
@@ -662,26 +660,32 @@
                   if (returnType.isNullable) {
                     // The value is a std::optional, so needs an extra layer of
                     // handling.
-                    elseBody = '''
-$prefix\tauto output_optional = $extractedValue;
-$prefix\tif (output_optional) {
-$prefix\t\twrapped.push_back($wrapperType(std::move(output_optional).value()));
-$prefix\t} else {
-$prefix\t\twrapped.push_back($nullValue);
-$prefix\t}${indent.newline}''';
+                    nonErrorPath = '''
+${prefix}auto output_optional = $extractedValue;
+${prefix}if (output_optional) {
+$prefix\twrapped.push_back($wrapperType(std::move(output_optional).value()));
+$prefix} else {
+$prefix\twrapped.push_back($nullValue);
+$prefix}''';
                   } else {
-                    elseBody =
-                        '$prefix\twrapped.push_back($wrapperType($extractedValue));${indent.newline}';
+                    nonErrorPath =
+                        '${prefix}wrapped.push_back($wrapperType($extractedValue));';
                   }
-                  ifCondition = 'output.has_error()';
+                  errorCondition = 'output.has_error()';
                   errorGetter = 'error';
                 }
-                return '${prefix}if ($ifCondition) {${indent.newline}'
-                    '$prefix\twrapped = WrapError(output.$errorGetter());${indent.newline}'
-                    '$prefix} else {${indent.newline}'
-                    '$elseBody'
-                    '$prefix}'
-                    '$prefix$reply';
+                // Ideally this code would use an initializer list to create
+                // an EncodableList inline, which would be less code. However,
+                // that would always copy the element, so the slightly more
+                // verbose create-and-push approach is used instead.
+                return '''
+${prefix}if ($errorCondition) {
+$prefix\treply(WrapError(output.$errorGetter()));
+$prefix\treturn;
+$prefix}
+${prefix}flutter::EncodableList wrapped;
+$nonErrorPath
+${prefix}reply(flutter::EncodableValue(std::move(wrapped)));''';
               }
 
               final HostDatatype returnType = getHostDatatype(
@@ -692,8 +696,8 @@
               final String returnTypeName = _apiReturnType(returnType);
               if (method.isAsynchronous) {
                 methodArgument.add(
-                  '[&wrapped, &reply]($returnTypeName&& output) {${indent.newline}'
-                  '${wrapResponse('\treply(flutter::EncodableValue(std::move(wrapped)));${indent.newline}', method.returnType)}'
+                  '[reply]($returnTypeName&& output) {${indent.newline}'
+                  '${wrapResponse(method.returnType, prefix: '\t')}${indent.newline}'
                   '}',
                 );
               }
@@ -703,21 +707,21 @@
                 indent.format('$call;');
               } else {
                 indent.writeln('$returnTypeName output = $call;');
-                indent.format(wrapResponse('', method.returnType));
+                indent.format(wrapResponse(method.returnType));
               }
             });
             indent.write('catch (const std::exception& exception) ');
             indent.scoped('{', '}', () {
-              indent.writeln('wrapped = WrapError(exception.what());');
-              if (method.isAsynchronous) {
-                indent.writeln(
-                    'reply(flutter::EncodableValue(std::move(wrapped)));');
-              }
+              // There is a potential here for `reply` to be called twice, which
+              // is a violation of the API contract, because there's no way of
+              // knowing whether or not the plugin code called `reply` before
+              // throwing. Since use of `@async` suggests that the reply is
+              // probably not sent within the scope of the stack, err on the
+              // side of potential double-call rather than no call (which is
+              // also an API violation) so that unexpected errors have a better
+              // chance of being caught and handled in a useful way.
+              indent.writeln('reply(WrapError(exception.what()));');
             });
-            if (!method.isAsynchronous) {
-              indent.writeln(
-                  'reply(flutter::EncodableValue(std::move(wrapped)));');
-            }
           });
         });
         indent.scoped(null, '}', () {
@@ -1187,15 +1191,15 @@
 
       indent.addln('');
       indent.format('''
-flutter::EncodableList ${api.name}::WrapError(std::string_view error_message) {
-\treturn flutter::EncodableList({
+flutter::EncodableValue ${api.name}::WrapError(std::string_view error_message) {
+\treturn flutter::EncodableValue(flutter::EncodableList{
 \t\tflutter::EncodableValue(std::string(error_message)),
 \t\tflutter::EncodableValue("Error"),
 \t\tflutter::EncodableValue()
 \t});
 }
-flutter::EncodableList ${api.name}::WrapError(const FlutterError& error) {
-\treturn flutter::EncodableList({
+flutter::EncodableValue ${api.name}::WrapError(const FlutterError& error) {
+\treturn flutter::EncodableValue(flutter::EncodableList{
 \t\tflutter::EncodableValue(error.message()),
 \t\tflutter::EncodableValue(error.code()),
 \t\terror.details()
diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart
index b1ee06b..4355096 100644
--- a/packages/pigeon/lib/generator_tools.dart
+++ b/packages/pigeon/lib/generator_tools.dart
@@ -9,7 +9,7 @@
 import 'ast.dart';
 
 /// The current version of pigeon. This must match the version in pubspec.yaml.
-const String pigeonVersion = '5.0.0';
+const String pigeonVersion = '5.0.1';
 
 /// Read all the content from [stdin] to a String.
 String readStdin() {
diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java
index 95b0e2a..ea8e343 100644
--- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java
+++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Autogenerated from Pigeon (v5.0.0), do not edit directly.
+// Autogenerated from Pigeon (v5.0.1), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 
 package com.example.alternate_language_test_plugin;
diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.h b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.h
index 1def5e7..2db8f71 100644
--- a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.h
+++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.h
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Autogenerated from Pigeon (v5.0.0), do not edit directly.
+// Autogenerated from Pigeon (v5.0.1), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 #import <Foundation/Foundation.h>
 @protocol FlutterBinaryMessenger;
diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.m
index 244b1e2..078bf32 100644
--- a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.m
+++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.m
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Autogenerated from Pigeon (v5.0.0), do not edit directly.
+// Autogenerated from Pigeon (v5.0.1), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 #import "CoreTests.gen.h"
 #import <Flutter/Flutter.h>
diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart
index fe0fe33..3560cc2 100644
--- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart
+++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Autogenerated from Pigeon (v5.0.0), do not edit directly.
+// Autogenerated from Pigeon (v5.0.1), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
 import 'dart:async';
diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt
index 61a957c..17d7e9f 100644
--- a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt
+++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 // 
-// Autogenerated from Pigeon (v5.0.0), do not edit directly.
+// Autogenerated from Pigeon (v5.0.1), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 
 package com.example.test_plugin
diff --git a/packages/pigeon/platform_tests/test_plugin/ios/Classes/CoreTests.gen.swift b/packages/pigeon/platform_tests/test_plugin/ios/Classes/CoreTests.gen.swift
index 844e541..bcf93bc 100644
--- a/packages/pigeon/platform_tests/test_plugin/ios/Classes/CoreTests.gen.swift
+++ b/packages/pigeon/platform_tests/test_plugin/ios/Classes/CoreTests.gen.swift
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 // 
-// Autogenerated from Pigeon (v5.0.0), do not edit directly.
+// Autogenerated from Pigeon (v5.0.1), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 
 import Foundation
diff --git a/packages/pigeon/platform_tests/test_plugin/macos/Classes/CoreTests.gen.swift b/packages/pigeon/platform_tests/test_plugin/macos/Classes/CoreTests.gen.swift
index 844e541..bcf93bc 100644
--- a/packages/pigeon/platform_tests/test_plugin/macos/Classes/CoreTests.gen.swift
+++ b/packages/pigeon/platform_tests/test_plugin/macos/Classes/CoreTests.gen.swift
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 // 
-// Autogenerated from Pigeon (v5.0.0), do not edit directly.
+// Autogenerated from Pigeon (v5.0.1), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 
 import Foundation
diff --git a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp
index 110c75e..98b9395 100644
--- a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp
+++ b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Autogenerated from Pigeon (v5.0.0), do not edit directly.
+// Autogenerated from Pigeon (v5.0.1), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 
 #undef _HAS_EXCEPTIONS
@@ -553,18 +553,18 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               std::optional<FlutterError> output = api->Noop();
               if (output.has_value()) {
-                wrapped = WrapError(output.value());
-              } else {
-                wrapped.push_back(flutter::EncodableValue());
+                reply(WrapError(output.value()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(flutter::EncodableValue());
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -580,13 +580,11 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_everything_arg = args.at(0);
               if (encodable_everything_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("everything_arg unexpectedly null.")));
+                reply(WrapError("everything_arg unexpectedly null."));
                 return;
               }
               const auto& everything_arg = std::any_cast<const AllTypes&>(
@@ -594,15 +592,16 @@
                       encodable_everything_arg));
               ErrorOr<AllTypes> output = api->EchoAllTypes(everything_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                wrapped.push_back(flutter::CustomEncodableValue(
-                    std::move(output).TakeValue()));
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(
+                  flutter::CustomEncodableValue(std::move(output).TakeValue()));
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -618,7 +617,6 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_everything_arg = args.at(0);
@@ -629,20 +627,21 @@
               ErrorOr<std::optional<AllNullableTypes>> output =
                   api->EchoAllNullableTypes(everything_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                auto output_optional = std::move(output).TakeValue();
-                if (output_optional) {
-                  wrapped.push_back(flutter::CustomEncodableValue(
-                      std::move(output_optional).value()));
-                } else {
-                  wrapped.push_back(flutter::EncodableValue());
-                }
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              auto output_optional = std::move(output).TakeValue();
+              if (output_optional) {
+                wrapped.push_back(flutter::CustomEncodableValue(
+                    std::move(output_optional).value()));
+              } else {
+                wrapped.push_back(flutter::EncodableValue());
+              }
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -658,18 +657,18 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               std::optional<FlutterError> output = api->ThrowError();
               if (output.has_value()) {
-                wrapped = WrapError(output.value());
-              } else {
-                wrapped.push_back(flutter::EncodableValue());
+                reply(WrapError(output.value()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(flutter::EncodableValue());
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -684,27 +683,26 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_an_int_arg = args.at(0);
               if (encodable_an_int_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("an_int_arg unexpectedly null.")));
+                reply(WrapError("an_int_arg unexpectedly null."));
                 return;
               }
               const int64_t an_int_arg = encodable_an_int_arg.LongValue();
               ErrorOr<int64_t> output = api->EchoInt(an_int_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                wrapped.push_back(
-                    flutter::EncodableValue(std::move(output).TakeValue()));
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(
+                  flutter::EncodableValue(std::move(output).TakeValue()));
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -720,28 +718,27 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_double_arg = args.at(0);
               if (encodable_a_double_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("a_double_arg unexpectedly null.")));
+                reply(WrapError("a_double_arg unexpectedly null."));
                 return;
               }
               const auto& a_double_arg =
                   std::get<double>(encodable_a_double_arg);
               ErrorOr<double> output = api->EchoDouble(a_double_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                wrapped.push_back(
-                    flutter::EncodableValue(std::move(output).TakeValue()));
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(
+                  flutter::EncodableValue(std::move(output).TakeValue()));
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -756,27 +753,26 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_bool_arg = args.at(0);
               if (encodable_a_bool_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("a_bool_arg unexpectedly null.")));
+                reply(WrapError("a_bool_arg unexpectedly null."));
                 return;
               }
               const auto& a_bool_arg = std::get<bool>(encodable_a_bool_arg);
               ErrorOr<bool> output = api->EchoBool(a_bool_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                wrapped.push_back(
-                    flutter::EncodableValue(std::move(output).TakeValue()));
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(
+                  flutter::EncodableValue(std::move(output).TakeValue()));
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -792,28 +788,27 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_string_arg = args.at(0);
               if (encodable_a_string_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("a_string_arg unexpectedly null.")));
+                reply(WrapError("a_string_arg unexpectedly null."));
                 return;
               }
               const auto& a_string_arg =
                   std::get<std::string>(encodable_a_string_arg);
               ErrorOr<std::string> output = api->EchoString(a_string_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                wrapped.push_back(
-                    flutter::EncodableValue(std::move(output).TakeValue()));
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(
+                  flutter::EncodableValue(std::move(output).TakeValue()));
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -829,13 +824,11 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_uint8_list_arg = args.at(0);
               if (encodable_a_uint8_list_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("a_uint8_list_arg unexpectedly null.")));
+                reply(WrapError("a_uint8_list_arg unexpectedly null."));
                 return;
               }
               const auto& a_uint8_list_arg =
@@ -843,15 +836,16 @@
               ErrorOr<std::vector<uint8_t>> output =
                   api->EchoUint8List(a_uint8_list_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                wrapped.push_back(
-                    flutter::EncodableValue(std::move(output).TakeValue()));
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(
+                  flutter::EncodableValue(std::move(output).TakeValue()));
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -867,28 +861,27 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_an_object_arg = args.at(0);
               if (encodable_an_object_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("an_object_arg unexpectedly null.")));
+                reply(WrapError("an_object_arg unexpectedly null."));
                 return;
               }
               const auto& an_object_arg = encodable_an_object_arg;
               ErrorOr<flutter::EncodableValue> output =
                   api->EchoObject(an_object_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                wrapped.push_back(
-                    flutter::EncodableValue(std::move(output).TakeValue()));
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(
+                  flutter::EncodableValue(std::move(output).TakeValue()));
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -904,13 +897,11 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_wrapper_arg = args.at(0);
               if (encodable_wrapper_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("wrapper_arg unexpectedly null.")));
+                reply(WrapError("wrapper_arg unexpectedly null."));
                 return;
               }
               const auto& wrapper_arg =
@@ -920,20 +911,21 @@
               ErrorOr<std::optional<std::string>> output =
                   api->ExtractNestedNullableString(wrapper_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                auto output_optional = std::move(output).TakeValue();
-                if (output_optional) {
-                  wrapped.push_back(flutter::EncodableValue(
-                      std::move(output_optional).value()));
-                } else {
-                  wrapped.push_back(flutter::EncodableValue());
-                }
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              auto output_optional = std::move(output).TakeValue();
+              if (output_optional) {
+                wrapped.push_back(flutter::EncodableValue(
+                    std::move(output_optional).value()));
+              } else {
+                wrapped.push_back(flutter::EncodableValue());
+              }
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -949,7 +941,6 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_nullable_string_arg = args.at(0);
@@ -958,15 +949,16 @@
               ErrorOr<AllNullableTypesWrapper> output =
                   api->CreateNestedNullableString(nullable_string_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                wrapped.push_back(flutter::CustomEncodableValue(
-                    std::move(output).TakeValue()));
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(
+                  flutter::CustomEncodableValue(std::move(output).TakeValue()));
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -982,7 +974,6 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_nullable_bool_arg = args.at(0);
@@ -1004,15 +995,16 @@
                   a_nullable_bool_arg, a_nullable_int_arg,
                   a_nullable_string_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                wrapped.push_back(flutter::CustomEncodableValue(
-                    std::move(output).TakeValue()));
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(
+                  flutter::CustomEncodableValue(std::move(output).TakeValue()));
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -1028,7 +1020,6 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_nullable_int_arg = args.at(0);
@@ -1043,20 +1034,21 @@
               ErrorOr<std::optional<int64_t>> output =
                   api->EchoNullableInt(a_nullable_int_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                auto output_optional = std::move(output).TakeValue();
-                if (output_optional) {
-                  wrapped.push_back(flutter::EncodableValue(
-                      std::move(output_optional).value()));
-                } else {
-                  wrapped.push_back(flutter::EncodableValue());
-                }
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              auto output_optional = std::move(output).TakeValue();
+              if (output_optional) {
+                wrapped.push_back(flutter::EncodableValue(
+                    std::move(output_optional).value()));
+              } else {
+                wrapped.push_back(flutter::EncodableValue());
+              }
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -1072,7 +1064,6 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_nullable_double_arg = args.at(0);
@@ -1081,20 +1072,21 @@
               ErrorOr<std::optional<double>> output =
                   api->EchoNullableDouble(a_nullable_double_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                auto output_optional = std::move(output).TakeValue();
-                if (output_optional) {
-                  wrapped.push_back(flutter::EncodableValue(
-                      std::move(output_optional).value()));
-                } else {
-                  wrapped.push_back(flutter::EncodableValue());
-                }
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              auto output_optional = std::move(output).TakeValue();
+              if (output_optional) {
+                wrapped.push_back(flutter::EncodableValue(
+                    std::move(output_optional).value()));
+              } else {
+                wrapped.push_back(flutter::EncodableValue());
+              }
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -1110,7 +1102,6 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_nullable_bool_arg = args.at(0);
@@ -1119,20 +1110,21 @@
               ErrorOr<std::optional<bool>> output =
                   api->EchoNullableBool(a_nullable_bool_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                auto output_optional = std::move(output).TakeValue();
-                if (output_optional) {
-                  wrapped.push_back(flutter::EncodableValue(
-                      std::move(output_optional).value()));
-                } else {
-                  wrapped.push_back(flutter::EncodableValue());
-                }
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              auto output_optional = std::move(output).TakeValue();
+              if (output_optional) {
+                wrapped.push_back(flutter::EncodableValue(
+                    std::move(output_optional).value()));
+              } else {
+                wrapped.push_back(flutter::EncodableValue());
+              }
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -1148,7 +1140,6 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_nullable_string_arg = args.at(0);
@@ -1157,20 +1148,21 @@
               ErrorOr<std::optional<std::string>> output =
                   api->EchoNullableString(a_nullable_string_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                auto output_optional = std::move(output).TakeValue();
-                if (output_optional) {
-                  wrapped.push_back(flutter::EncodableValue(
-                      std::move(output_optional).value()));
-                } else {
-                  wrapped.push_back(flutter::EncodableValue());
-                }
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              auto output_optional = std::move(output).TakeValue();
+              if (output_optional) {
+                wrapped.push_back(flutter::EncodableValue(
+                    std::move(output_optional).value()));
+              } else {
+                wrapped.push_back(flutter::EncodableValue());
+              }
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -1186,7 +1178,6 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_nullable_uint8_list_arg = args.at(0);
@@ -1196,20 +1187,21 @@
               ErrorOr<std::optional<std::vector<uint8_t>>> output =
                   api->EchoNullableUint8List(a_nullable_uint8_list_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                auto output_optional = std::move(output).TakeValue();
-                if (output_optional) {
-                  wrapped.push_back(flutter::EncodableValue(
-                      std::move(output_optional).value()));
-                } else {
-                  wrapped.push_back(flutter::EncodableValue());
-                }
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              auto output_optional = std::move(output).TakeValue();
+              if (output_optional) {
+                wrapped.push_back(flutter::EncodableValue(
+                    std::move(output_optional).value()));
+              } else {
+                wrapped.push_back(flutter::EncodableValue());
+              }
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -1225,7 +1217,6 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_nullable_object_arg = args.at(0);
@@ -1234,20 +1225,21 @@
               ErrorOr<std::optional<flutter::EncodableValue>> output =
                   api->EchoNullableObject(a_nullable_object_arg);
               if (output.has_error()) {
-                wrapped = WrapError(output.error());
-              } else {
-                auto output_optional = std::move(output).TakeValue();
-                if (output_optional) {
-                  wrapped.push_back(flutter::EncodableValue(
-                      std::move(output_optional).value()));
-                } else {
-                  wrapped.push_back(flutter::EncodableValue());
-                }
+                reply(WrapError(output.error()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              auto output_optional = std::move(output).TakeValue();
+              if (output_optional) {
+                wrapped.push_back(flutter::EncodableValue(
+                    std::move(output_optional).value()));
+              } else {
+                wrapped.push_back(flutter::EncodableValue());
+              }
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -1262,20 +1254,18 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
-              api->NoopAsync(
-                  [&wrapped, &reply](std::optional<FlutterError>&& output) {
-                    if (output.has_value()) {
-                      wrapped = WrapError(output.value());
-                    } else {
-                      wrapped.push_back(flutter::EncodableValue());
-                    }
-                    reply(flutter::EncodableValue(std::move(wrapped)));
-                  });
+              api->NoopAsync([reply](std::optional<FlutterError>&& output) {
+                if (output.has_value()) {
+                  reply(WrapError(output.value()));
+                  return;
+                }
+                flutter::EncodableList wrapped;
+                wrapped.push_back(flutter::EncodableValue());
+                reply(flutter::EncodableValue(std::move(wrapped)));
+              });
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
-              reply(flutter::EncodableValue(std::move(wrapped)));
+              reply(WrapError(exception.what()));
             }
           });
     } else {
@@ -1292,31 +1282,28 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_string_arg = args.at(0);
               if (encodable_a_string_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("a_string_arg unexpectedly null.")));
+                reply(WrapError("a_string_arg unexpectedly null."));
                 return;
               }
               const auto& a_string_arg =
                   std::get<std::string>(encodable_a_string_arg);
               api->EchoAsyncString(
-                  a_string_arg,
-                  [&wrapped, &reply](ErrorOr<std::string>&& output) {
+                  a_string_arg, [reply](ErrorOr<std::string>&& output) {
                     if (output.has_error()) {
-                      wrapped = WrapError(output.error());
-                    } else {
-                      wrapped.push_back(flutter::EncodableValue(
-                          std::move(output).TakeValue()));
+                      reply(WrapError(output.error()));
+                      return;
                     }
+                    flutter::EncodableList wrapped;
+                    wrapped.push_back(
+                        flutter::EncodableValue(std::move(output).TakeValue()));
                     reply(flutter::EncodableValue(std::move(wrapped)));
                   });
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
-              reply(flutter::EncodableValue(std::move(wrapped)));
+              reply(WrapError(exception.what()));
             }
           });
     } else {
@@ -1333,20 +1320,19 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               api->CallFlutterNoop(
-                  [&wrapped, &reply](std::optional<FlutterError>&& output) {
+                  [reply](std::optional<FlutterError>&& output) {
                     if (output.has_value()) {
-                      wrapped = WrapError(output.value());
-                    } else {
-                      wrapped.push_back(flutter::EncodableValue());
+                      reply(WrapError(output.value()));
+                      return;
                     }
+                    flutter::EncodableList wrapped;
+                    wrapped.push_back(flutter::EncodableValue());
                     reply(flutter::EncodableValue(std::move(wrapped)));
                   });
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
-              reply(flutter::EncodableValue(std::move(wrapped)));
+              reply(WrapError(exception.what()));
             }
           });
     } else {
@@ -1363,31 +1349,28 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               const auto& args = std::get<flutter::EncodableList>(message);
               const auto& encodable_a_string_arg = args.at(0);
               if (encodable_a_string_arg.IsNull()) {
-                reply(flutter::EncodableValue(
-                    WrapError("a_string_arg unexpectedly null.")));
+                reply(WrapError("a_string_arg unexpectedly null."));
                 return;
               }
               const auto& a_string_arg =
                   std::get<std::string>(encodable_a_string_arg);
               api->CallFlutterEchoString(
-                  a_string_arg,
-                  [&wrapped, &reply](ErrorOr<std::string>&& output) {
+                  a_string_arg, [reply](ErrorOr<std::string>&& output) {
                     if (output.has_error()) {
-                      wrapped = WrapError(output.error());
-                    } else {
-                      wrapped.push_back(flutter::EncodableValue(
-                          std::move(output).TakeValue()));
+                      reply(WrapError(output.error()));
+                      return;
                     }
+                    flutter::EncodableList wrapped;
+                    wrapped.push_back(
+                        flutter::EncodableValue(std::move(output).TakeValue()));
                     reply(flutter::EncodableValue(std::move(wrapped)));
                   });
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
-              reply(flutter::EncodableValue(std::move(wrapped)));
+              reply(WrapError(exception.what()));
             }
           });
     } else {
@@ -1396,17 +1379,17 @@
   }
 }
 
-flutter::EncodableList HostIntegrationCoreApi::WrapError(
+flutter::EncodableValue HostIntegrationCoreApi::WrapError(
     std::string_view error_message) {
-  return flutter::EncodableList(
-      {flutter::EncodableValue(std::string(error_message)),
-       flutter::EncodableValue("Error"), flutter::EncodableValue()});
+  return flutter::EncodableValue(flutter::EncodableList{
+      flutter::EncodableValue(std::string(error_message)),
+      flutter::EncodableValue("Error"), flutter::EncodableValue()});
 }
-flutter::EncodableList HostIntegrationCoreApi::WrapError(
+flutter::EncodableValue HostIntegrationCoreApi::WrapError(
     const FlutterError& error) {
-  return flutter::EncodableList({flutter::EncodableValue(error.message()),
-                                 flutter::EncodableValue(error.code()),
-                                 error.details()});
+  return flutter::EncodableValue(flutter::EncodableList{
+      flutter::EncodableValue(error.message()),
+      flutter::EncodableValue(error.code()), error.details()});
 }
 
 FlutterIntegrationCoreApiCodecSerializer::
@@ -1561,18 +1544,18 @@
       channel->SetMessageHandler(
           [api](const flutter::EncodableValue& message,
                 const flutter::MessageReply<flutter::EncodableValue>& reply) {
-            flutter::EncodableList wrapped;
             try {
               std::optional<FlutterError> output = api->Noop();
               if (output.has_value()) {
-                wrapped = WrapError(output.value());
-              } else {
-                wrapped.push_back(flutter::EncodableValue());
+                reply(WrapError(output.value()));
+                return;
               }
+              flutter::EncodableList wrapped;
+              wrapped.push_back(flutter::EncodableValue());
+              reply(flutter::EncodableValue(std::move(wrapped)));
             } catch (const std::exception& exception) {
-              wrapped = WrapError(exception.what());
+              reply(WrapError(exception.what()));
             }
-            reply(flutter::EncodableValue(std::move(wrapped)));
           });
     } else {
       channel->SetMessageHandler(nullptr);
@@ -1580,16 +1563,16 @@
   }
 }
 
-flutter::EncodableList HostTrivialApi::WrapError(
+flutter::EncodableValue HostTrivialApi::WrapError(
     std::string_view error_message) {
-  return flutter::EncodableList(
-      {flutter::EncodableValue(std::string(error_message)),
-       flutter::EncodableValue("Error"), flutter::EncodableValue()});
+  return flutter::EncodableValue(flutter::EncodableList{
+      flutter::EncodableValue(std::string(error_message)),
+      flutter::EncodableValue("Error"), flutter::EncodableValue()});
 }
-flutter::EncodableList HostTrivialApi::WrapError(const FlutterError& error) {
-  return flutter::EncodableList({flutter::EncodableValue(error.message()),
-                                 flutter::EncodableValue(error.code()),
-                                 error.details()});
+flutter::EncodableValue HostTrivialApi::WrapError(const FlutterError& error) {
+  return flutter::EncodableValue(flutter::EncodableList{
+      flutter::EncodableValue(error.message()),
+      flutter::EncodableValue(error.code()), error.details()});
 }
 
 }  // namespace core_tests_pigeontest
diff --git a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.h b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.h
index 527a0ff..aac405e 100644
--- a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.h
+++ b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.h
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
-// Autogenerated from Pigeon (v5.0.0), do not edit directly.
+// Autogenerated from Pigeon (v5.0.1), do not edit directly.
 // See also: https://pub.dev/packages/pigeon
 
 #ifndef PIGEON_CORE_TESTS_PIGEONTEST_H_
@@ -336,8 +336,8 @@
   // the `binary_messenger`.
   static void SetUp(flutter::BinaryMessenger* binary_messenger,
                     HostIntegrationCoreApi* api);
-  static flutter::EncodableList WrapError(std::string_view error_message);
-  static flutter::EncodableList WrapError(const FlutterError& error);
+  static flutter::EncodableValue WrapError(std::string_view error_message);
+  static flutter::EncodableValue WrapError(const FlutterError& error);
 
  protected:
   HostIntegrationCoreApi() = default;
@@ -405,8 +405,8 @@
   // `binary_messenger`.
   static void SetUp(flutter::BinaryMessenger* binary_messenger,
                     HostTrivialApi* api);
-  static flutter::EncodableList WrapError(std::string_view error_message);
-  static flutter::EncodableList WrapError(const FlutterError& error);
+  static flutter::EncodableValue WrapError(std::string_view error_message);
+  static flutter::EncodableValue WrapError(const FlutterError& error);
 
  protected:
   HostTrivialApi() = default;
diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml
index e4ada89..f2a5a9a 100644
--- a/packages/pigeon/pubspec.yaml
+++ b/packages/pigeon/pubspec.yaml
@@ -2,7 +2,7 @@
 description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
 repository: https://github.com/flutter/packages/tree/main/packages/pigeon
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3Apigeon
-version: 5.0.0 # This must match the version in lib/generator_tools.dart
+version: 5.0.1 # This must match the version in lib/generator_tools.dart
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
diff --git a/packages/pigeon/test/cpp_generator_test.dart b/packages/pigeon/test/cpp_generator_test.dart
index 172ce2e..d8e9917 100644
--- a/packages/pigeon/test/cpp_generator_test.dart
+++ b/packages/pigeon/test/cpp_generator_test.dart
@@ -1300,4 +1300,64 @@
     expect(code, isNot(contains('reply(wrap')));
     expect(code, contains('reply(flutter::EncodableValue('));
   });
+
+  test('does not keep unowned references in async handlers', () {
+    final Root root = Root(apis: <Api>[
+      Api(name: 'HostApi', location: ApiLocation.host, methods: <Method>[
+        Method(
+          name: 'noop',
+          arguments: <NamedType>[],
+          returnType: const TypeDeclaration.voidDeclaration(),
+          isAsynchronous: true,
+        ),
+        Method(
+          name: 'doSomething',
+          arguments: <NamedType>[
+            NamedType(
+                type: const TypeDeclaration(
+                  baseName: 'int',
+                  isNullable: false,
+                ),
+                name: '')
+          ],
+          returnType:
+              const TypeDeclaration(baseName: 'double', isNullable: false),
+          isAsynchronous: true,
+        ),
+      ]),
+      Api(name: 'FlutterApi', location: ApiLocation.flutter, methods: <Method>[
+        Method(
+          name: 'noop',
+          arguments: <NamedType>[],
+          returnType: const TypeDeclaration.voidDeclaration(),
+          isAsynchronous: true,
+        ),
+        Method(
+          name: 'doSomething',
+          arguments: <NamedType>[
+            NamedType(
+                type: const TypeDeclaration(
+                  baseName: 'String',
+                  isNullable: false,
+                ),
+                name: '')
+          ],
+          returnType:
+              const TypeDeclaration(baseName: 'bool', isNullable: false),
+          isAsynchronous: true,
+        ),
+      ])
+    ], classes: <Class>[], enums: <Enum>[]);
+    final StringBuffer sink = StringBuffer();
+    generateCppSource(const CppOptions(), root, sink);
+    final String code = sink.toString();
+    // Nothing should be captured by reference for async handlers, since their
+    // lifetime is unknown (and expected to be longer than the stack's).
+    expect(code, isNot(contains('&reply')));
+    expect(code, isNot(contains('&wrapped')));
+    // Check for the exact capture format that is currently being used, to
+    // ensure that the negative tests above get updated if there are any
+    // changes to lambda capture.
+    expect(code, contains('[reply]('));
+  });
 }