Skip to content

Commit 952402d

Browse files
authored
Fix reducer errors to return message not stack trace (#3965)
# Description of Changes This PR fixes a C# reducer error-reporting issue where exceptions thrown in reducers were returned to clients with full stack traces, as reported in [#3959](#3959). - Updated the C# reducer host-call error serialization to return only `Exception.Message` (instead of `Exception.ToString()`), preventing server-side stack traces from being leaked to clients. - Added a C# regression-test client assertion to validate reducer failures do not contain stack traces: - `exception.Message` matches the thrown message exactly - the message does not contain newlines or `" at "` stack-trace markers # API and ABI breaking changes None. - No schema or wire-format changes. - Behavior change is limited to the *contents* of reducer error strings returned to clients (stack traces removed). # Expected complexity level and risk 2 - Low - Change is isolated to C# reducer error formatting plus a regression assertion. - Removes unintended information exposure without affecting reducer success paths. # Testing - [X] Ran C# regression-tests client; verified reducer error message is preserved and stack trace is not present.
1 parent 94adfdc commit 952402d

2 files changed

Lines changed: 15 additions & 2 deletions

File tree

  • crates/bindings-csharp/Runtime/Internal
  • sdks/csharp/examples~/regression-tests/client

crates/bindings-csharp/Runtime/Internal/Module.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ BytesSink error
312312
}
313313
catch (Exception e)
314314
{
315-
var error_str = e.ToString();
315+
var error_str = e.Message ?? e.GetType().FullName;
316316
var error_bytes = System.Text.Encoding.UTF8.GetBytes(error_str);
317317
error.Write(error_bytes);
318318
return Errno.HOST_CALL_FAILURE;

sdks/csharp/examples~/regression-tests/client/Program.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
const string HOST = "http://localhost:3000";
1414
const string DBNAME = "btree-repro";
15+
const string THROW_ERROR_MESSAGE = "this is an error";
1516

1617
DbConnection ConnectToDB()
1718
{
@@ -94,6 +95,7 @@ void OnConnected(DbConnection conn, Identity identity, string authToken)
9495
{
9596
Log.Info($"Got OnUnhandledReducerError: {exception}");
9697
waiting--;
98+
ValidateReducerErrorDoesNotContainStackTrace(exception);
9799
ValidateBTreeIndexes(ctx);
98100
ValidateNullableVecView(ctx);
99101
};
@@ -174,6 +176,17 @@ void ValidateNullableVecView(
174176
}
175177
}
176178

179+
void ValidateReducerErrorDoesNotContainStackTrace(Exception exception)
180+
{
181+
Debug.Assert(
182+
exception.Message == THROW_ERROR_MESSAGE,
183+
$"Expected reducer error message '{THROW_ERROR_MESSAGE}', got '{exception.Message}'"
184+
);
185+
Debug.Assert(!exception.Message.Contains("\n"), "Reducer error message should not contain newline");
186+
Debug.Assert(!exception.Message.Contains("\r"), "Reducer error message should not contain newline");
187+
Debug.Assert(!exception.Message.Contains(" at "), "Reducer error message should not contain stack trace");
188+
}
189+
177190
void OnSubscriptionApplied(SubscriptionEventContext context)
178191
{
179192
applied = true;
@@ -194,7 +207,7 @@ void OnSubscriptionApplied(SubscriptionEventContext context)
194207

195208
Log.Debug("Calling ThrowError");
196209
waiting++;
197-
context.Reducers.ThrowError("this is an error");
210+
context.Reducers.ThrowError(THROW_ERROR_MESSAGE);
198211

199212
Log.Debug("Calling InsertResult");
200213
waiting++;

0 commit comments

Comments
 (0)