Skip to content

Send a ServerFailureResult's UserMessage in the 500's body; 3.3.0 - #9

Closed
lewisrenfrew wants to merge 2 commits into
mainfrom
server-failure-message
Closed

lewisrenfrew wants to merge 2 commits into
mainfrom
server-failure-message

Conversation

@lewisrenfrew

Copy link
Copy Markdown
Collaborator

A ServerFailureResult (500) now sends its UserMessage in the response body; 3.3.0.

  • What's sent: only UserMessage, the text written to be shown. That's new in Linn.Common.Facade 13.6.0, e.g. "The change was saved, but writing its log failed - check it before trying again", which tells a caller not to just retry.
  • What isn't: Message is diagnostic detail and is never sent. Existing ServerFailureResults have no UserMessage, so they stay an empty 500. That includes Portal's, some of which carry upstream services' raw errors, so nothing internal starts leaking when apps upgrade.
  • Dependencies: needs Linn.Common.Facade 13.6.0 (linn/Common.Facade#12), so publish that first.
  • Tests: two new ones in WhenWritingAServerFailure, one sending the user message without the detail and one keeping a message-only result's body empty. All 25 tests pass against a local pack of Facade 13.6.0, and the first fails against the old writer.

Like BadRequestResult, UnauthorisedResult and ForbiddenResult - e.g. Linn.Common.Facade 13.6's "The
change was saved, but ... failed", so a caller knows not to simply retry. Empty body when there's no
message, as before.
Message is diagnostic detail and stays unsent, so existing ServerFailureResults (e.g. carrying an
upstream service's raw error) are still an empty 500. Needs Linn.Common.Facade 13.6.0.
Copilot AI balanced review requested due to automatic review settings October 5, 2026 11:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The separate stream-result handler still discards UserMessage for server failures.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Adds safe user-facing messages to 500 responses while withholding diagnostic details.

Changes:

  • Serializes ServerFailureResult.UserMessage.
  • Adds regression tests.
  • Updates Facade dependency and package version.
File Description
src/​Handlers/​ResultResponseWriter.cs Writes user-safe 500 response bodies.
src/​Linn.Common.Service.csproj Updates package and dependency versions.
tests/​WhenWritingAServerFailure.cs Tests safe and empty 500 bodies.
tests/​Linn.Common.Service.Tests.csproj Updates the test dependency.
CHANGELOG.md Documents version 3.3.0.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +80 to +85
case ServerFailureResult<T> r:
res.StatusCode = 500;

// only the UserMessage, written to be shown (e.g. Linn.Common.Facade's "The change was
// saved, but ... failed"); Message is diagnostic detail and is never sent
await res.WriteAsync(this.SerializeOptional(NullIfEmpty(r.UserMessage), null), cancellationToken);
@lewisrenfrew

Copy link
Copy Markdown
Collaborator Author

Closing: the "saved, but something failed afterwards" reporting it supported has been dropped from linn/Common.Facade#12, so there's nothing to send. The review found a separate, older bug worth its own PR some time: CsvSerializer writes a message string one character per row, garbling 400/401/403 bodies sent as CSV (the fix is on this branch, commit df3660c).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants