diff --git a/examples/Error/Client/Client.csproj b/examples/Error/Client/Client.csproj
new file mode 100644
index 000000000..6b5421801
--- /dev/null
+++ b/examples/Error/Client/Client.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ net8.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/Error/Client/Program.cs b/examples/Error/Client/Program.cs
new file mode 100644
index 000000000..3021039b3
--- /dev/null
+++ b/examples/Error/Client/Program.cs
@@ -0,0 +1,57 @@
+#region Copyright notice and license
+
+// Copyright 2019 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using Google.Rpc;
+using Greet;
+using Grpc.Core;
+using Grpc.Net.Client;
+using Grpc.StatusProto;
+
+using var channel = GrpcChannel.ForAddress("https://localhost:5001");
+var client = new Greeter.GreeterClient(channel);
+
+Console.WriteLine("Hello world app");
+Console.WriteLine("===============");
+
+while (true)
+{
+ Console.WriteLine();
+
+ Console.Write("Enter name: ");
+ var name = Console.ReadLine();
+
+ try
+ {
+ var reply = await client.SayHelloAsync(new HelloRequest { Name = name });
+ Console.WriteLine("Greeting: " + reply.Message);
+ }
+ catch (RpcException ex)
+ {
+ Console.WriteLine($"Server error: {ex.Status.Detail}");
+
+ var badRequest = ex.GetRpcStatus()?.GetStatusDetail();
+ if (badRequest != null)
+ {
+ foreach (var fieldViolation in badRequest.FieldViolations)
+ {
+ Console.WriteLine($"Field: {fieldViolation.Field}");
+ Console.WriteLine($"Description: {fieldViolation.Description}");
+ }
+ }
+ }
+}
diff --git a/examples/Error/Error.sln b/examples/Error/Error.sln
new file mode 100644
index 000000000..c15fc0471
--- /dev/null
+++ b/examples/Error/Error.sln
@@ -0,0 +1,61 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.8.34004.107
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{534AC5F8-2DF2-40BD-87A5-B3D8310118C4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{48A1D3BC-A14B-436A-8822-6DE2BEF8B747}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.StatusProto", "..\..\src\Grpc.StatusProto\Grpc.StatusProto.csproj", "{08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Core.Api", "..\..\src\Grpc.Core.Api\Grpc.Core.Api.csproj", "{E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Net.Client", "..\..\src\Grpc.Net.Client\Grpc.Net.Client.csproj", "{E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.Net.Common", "..\..\src\Grpc.Net.Common\Grpc.Net.Common.csproj", "{23678E37-37D4-4543-9961-403B3760862B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grpc.AspNetCore.Server", "..\..\src\Grpc.AspNetCore.Server\Grpc.AspNetCore.Server.csproj", "{A1368174-6D27-49F1-B6DC-F1868CAE000F}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {534AC5F8-2DF2-40BD-87A5-B3D8310118C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {534AC5F8-2DF2-40BD-87A5-B3D8310118C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {534AC5F8-2DF2-40BD-87A5-B3D8310118C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {534AC5F8-2DF2-40BD-87A5-B3D8310118C4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {48A1D3BC-A14B-436A-8822-6DE2BEF8B747}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {48A1D3BC-A14B-436A-8822-6DE2BEF8B747}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {48A1D3BC-A14B-436A-8822-6DE2BEF8B747}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {48A1D3BC-A14B-436A-8822-6DE2BEF8B747}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08BEBE52-D94B-449B-A5B5-9ABAABDE7CB2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E00E8BDE-19A9-47D7-B2D8-B304B2DEBAF3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E2C141A0-E21F-4F0F-9E32-FD90C57E8AD0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {23678E37-37D4-4543-9961-403B3760862B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {23678E37-37D4-4543-9961-403B3760862B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {23678E37-37D4-4543-9961-403B3760862B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {23678E37-37D4-4543-9961-403B3760862B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A1368174-6D27-49F1-B6DC-F1868CAE000F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A1368174-6D27-49F1-B6DC-F1868CAE000F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A1368174-6D27-49F1-B6DC-F1868CAE000F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A1368174-6D27-49F1-B6DC-F1868CAE000F}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {D22B3129-3BFB-41FA-9FCE-E45EBEF8C2DD}
+ EndGlobalSection
+EndGlobal
diff --git a/examples/Error/Proto/greet.proto b/examples/Error/Proto/greet.proto
new file mode 100644
index 000000000..26d0c794d
--- /dev/null
+++ b/examples/Error/Proto/greet.proto
@@ -0,0 +1,33 @@
+// Copyright 2019 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package greet;
+
+// The greeting service definition.
+service Greeter {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply);
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+}
+
+// The response message containing the greetings
+message HelloReply {
+ string message = 1;
+}
diff --git a/examples/Error/Server/Program.cs b/examples/Error/Server/Program.cs
new file mode 100644
index 000000000..74aeee754
--- /dev/null
+++ b/examples/Error/Server/Program.cs
@@ -0,0 +1,27 @@
+#region Copyright notice and license
+
+// Copyright 2019 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using Server;
+
+var builder = WebApplication.CreateBuilder(args);
+builder.Services.AddGrpc();
+
+var app = builder.Build();
+app.MapGrpcService();
+
+app.Run();
diff --git a/examples/Error/Server/Server.csproj b/examples/Error/Server/Server.csproj
new file mode 100644
index 000000000..c35044e3c
--- /dev/null
+++ b/examples/Error/Server/Server.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net8.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/Error/Server/Services/GreeterService.cs b/examples/Error/Server/Services/GreeterService.cs
new file mode 100644
index 000000000..a9e9adbb3
--- /dev/null
+++ b/examples/Error/Server/Services/GreeterService.cs
@@ -0,0 +1,63 @@
+#region Copyright notice and license
+
+// Copyright 2019 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System.Runtime.CompilerServices;
+using Google.Protobuf.WellKnownTypes;
+using Google.Rpc;
+using Greet;
+using Grpc.Core;
+using Grpc.StatusProto;
+
+namespace Server
+{
+ public class GreeterService : Greeter.GreeterBase
+ {
+ public override Task SayHello(HelloRequest request, ServerCallContext context)
+ {
+ ArgumentNotNullOrEmpty(request.Name);
+
+ return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
+ }
+
+ private static void ArgumentNotNullOrEmpty(string value, [CallerArgumentExpression(nameof(value))] string? paramName = null)
+ {
+ if (string.IsNullOrEmpty(value))
+ {
+ throw new Google.Rpc.Status
+ {
+ Code = (int)Code.InvalidArgument,
+ Message = "Bad request",
+ Details =
+ {
+ Any.Pack(new BadRequest
+ {
+ FieldViolations =
+ {
+ new BadRequest.Types.FieldViolation
+ {
+ Field = paramName,
+ Description = "Value is null or empty"
+ }
+ }
+ })
+ }
+ }.ToRpcException();
+ }
+ }
+ }
+}
diff --git a/examples/Error/Server/appsettings.Development.json b/examples/Error/Server/appsettings.Development.json
new file mode 100644
index 000000000..fe20c40cc
--- /dev/null
+++ b/examples/Error/Server/appsettings.Development.json
@@ -0,0 +1,10 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Grpc": "Information",
+ "Microsoft": "Information"
+ }
+ }
+}
diff --git a/examples/Error/Server/appsettings.json b/examples/Error/Server/appsettings.json
new file mode 100644
index 000000000..f5f63744b
--- /dev/null
+++ b/examples/Error/Server/appsettings.json
@@ -0,0 +1,13 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information"
+ }
+ },
+ "AllowedHosts": "*",
+ "Kestrel": {
+ "EndpointDefaults": {
+ "Protocols": "Http2"
+ }
+ }
+}