Skip to content

Comments

distinguish user errors from internal errors#7980

Open
aaryan359 wants to merge 7 commits intojaegertracing:mainfrom
aaryan359:fix/frontend-error-handling
Open

distinguish user errors from internal errors#7980
aaryan359 wants to merge 7 commits intojaegertracing:mainfrom
aaryan359:fix/frontend-error-handling

Conversation

@aaryan359
Copy link
Contributor

@aaryan359 aaryan359 commented Feb 4, 2026

Which problem is this PR solving?

Description of the changes

  • Distinguish user-caused errors from internal server errors in the HotROD example.
  • Return appropriate HTTP status codes (e.g. 400 Bad Request) for invalid input instead of 500 Internal Server Error.
  • Improve error handling to align with expected REST API behavior and existing TODO comments in the code.

How was this change tested?

  • Built and ran the HotROD example locally.
  • Sent requests with invalid customer IDs using curl and verified the service returns a clear error message with the correct HTTP status code.
  • Confirmed existing functionality remains unchanged for valid requests.
Screenshot from 2026-02-04 11-38-26

Checklist

@aaryan359 aaryan359 requested a review from a team as a code owner February 4, 2026 06:11
@dosubot dosubot bot added the enhancement label Feb 4, 2026
@codecov
Copy link

codecov bot commented Feb 4, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.48%. Comparing base (9c047cb) to head (b2ce304).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7980      +/-   ##
==========================================
+ Coverage   95.47%   95.48%   +0.01%     
==========================================
  Files         316      316              
  Lines       16756    16756              
==========================================
+ Hits        15997    15999       +2     
+ Misses        593      592       -1     
+ Partials      166      165       -1     
Flag Coverage Δ
badger_v1 9.16% <ø> (ø)
badger_v2 1.89% <ø> (ø)
cassandra-4.x-v1-manual 13.35% <ø> (ø)
cassandra-4.x-v2-auto 1.88% <ø> (ø)
cassandra-4.x-v2-manual 1.88% <ø> (ø)
cassandra-5.x-v1-manual 13.35% <ø> (ø)
cassandra-5.x-v2-auto 1.88% <ø> (ø)
cassandra-5.x-v2-manual 1.88% <ø> (ø)
clickhouse 1.97% <ø> (ø)
elasticsearch-6.x-v1 17.19% <ø> (ø)
elasticsearch-7.x-v1 17.22% <ø> (ø)
elasticsearch-8.x-v1 17.37% <ø> (ø)
elasticsearch-8.x-v2 1.89% <ø> (ø)
elasticsearch-9.x-v2 1.89% <ø> (ø)
grpc_v1 8.40% <ø> (ø)
grpc_v2 1.89% <ø> (ø)
kafka-3.x-v2 1.89% <ø> (ø)
memory_v2 1.89% <ø> (ø)
opensearch-1.x-v1 17.26% <ø> (ø)
opensearch-2.x-v1 17.26% <ø> (ø)
opensearch-2.x-v2 1.89% <ø> (ø)
opensearch-3.x-v2 1.89% <ø> (ø)
query 1.89% <ø> (ø)
tailsampling-processor 0.54% <ø> (ø)
unittests 94.16% <ø> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aaryan359
Copy link
Contributor Author

aaryan359 commented Feb 7, 2026

@jkowall and @yurishkuro, can you review this please? Does this look good?

Signed-off-by: aaryan359 <aaryanmeena96@gmail.com>
Signed-off-by: aaryan359 <aaryanmeena96@gmail.com>
Signed-off-by: aaryan359 <aaryanmeena96@gmail.com>
Signed-off-by: aaryan359 <aaryanmeena96@gmail.com>
Signed-off-by: aaryan359 <aaryanmeena96@gmail.com>
@jkowall
Copy link
Contributor

jkowall commented Feb 8, 2026

Seems like some issue with the tests, please verify and fix. Copilot is reviewing it now too. Thanks.

@github-actions github-actions bot added the waiting-for-author PR is waiting for author to respond to maintainer's comments label Feb 8, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the HotROD example’s error handling so that user-caused failures (e.g., invalid customer IDs) are surfaced as client errors (400-level) instead of being treated as internal server failures (500).

Changes:

  • Introduces typed HTTP-related errors (BadRequestError, HTTPError) and an auto-mapping helper (HandleErrorAuto) in httperr.
  • Updates frontend and customer services to use HandleErrorAuto when handling downstream/service errors.
  • Adds unit tests covering the new error types/handler behavior and the customer database invalid-customer path.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
examples/hotrod/services/frontend/server.go Uses auto HTTP status mapping when bestETA.Get() fails to avoid always returning 500.
examples/hotrod/services/customer/server.go Uses auto HTTP status mapping for database lookup errors.
examples/hotrod/services/customer/database.go Returns a typed bad-request error for invalid customer IDs.
examples/hotrod/pkg/tracing/http.go Propagates downstream HTTP status codes via a typed HTTPError.
examples/hotrod/pkg/httperr/httperr.go Adds typed errors and HandleErrorAuto to map errors to appropriate status codes.
examples/hotrod/pkg/httperr/httperr_test.go Adds tests for HandleError, HandleErrorAuto, and the new error constructors.
examples/hotrod/services/customer/database_test.go Adds tests validating success cases and the invalid-customer error type.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -17,3 +49,27 @@ func HandleError(w http.ResponseWriter, err error, statusCode int) bool {
http.Error(w, string(err.Error()), statusCode)
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

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

Redundant conversion: err.Error() already returns a string, so wrapping it in string(...) is unnecessary and may be flagged by linters (e.g., staticcheck S1025).

Suggested change
http.Error(w, string(err.Error()), statusCode)
http.Error(w, err.Error(), statusCode)

Copilot uses AI. Check for mistakes.
"net/http"
)

// BadRequestError represents a user error (4xx status code)
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

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

The comment says BadRequestError represents a user error "(4xx status code)", but the implementation only maps this type to HTTP 400. Consider updating the comment to avoid implying it can represent other 4xx codes.

Suggested change
// BadRequestError represents a user error (4xx status code)
// BadRequestError represents a user error mapped to HTTP 400 (Bad Request)

Copilot uses AI. Check for mistakes.
Signed-off-by: aaryan359 <aaryanmeena96@gmail.com>
@github-actions github-actions bot removed the waiting-for-author PR is waiting for author to respond to maintainer's comments label Feb 8, 2026
@aaryan359
Copy link
Contributor Author

aaryan359 commented Feb 8, 2026

@jkowall, I fixed the test and also improved the code review. Now is it looking good.

Copilot AI review requested due to automatic review settings February 11, 2026 15:20
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to 117
if httperr.HandleErrorAuto(w, err) {
s.logger.For(ctx).Error("request failed", zap.Error(err))
return
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

HandleErrorAuto may be returning a 4xx (e.g., invalid customer ID), but this branch always logs at Error level. That can create noisy logs/alerts for user-caused failures. Consider downgrading the log level for client errors (e.g., BadRequestError or HTTPError with StatusCode < 500) and reserving Error logs for 5xx/unexpected errors.

Copilot uses AI. Check for mistakes.
Comment on lines +81 to 83
if httperr.HandleErrorAuto(w, err) {
s.logger.For(ctx).Error("request failed", zap.Error(err))
return
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

Same as frontend: this logs at Error level even when HandleErrorAuto maps the error to a 4xx user error. Consider logging 4xx as Info/Debug and using Error only for 5xx, based on BadRequestError / HTTPError.StatusCode.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +25
func TestDatabaseGetValidCustomer(t *testing.T) {
logger := log.NewFactory(zap.NewNop())
db := newDatabase(trace.NewNoopTracerProvider().Tracer("test"), logger)

// Test getting a valid customer
customer, err := db.Get(context.Background(), 123)
require.NoError(t, err)
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

These unit tests call db.Get, which sleeps using config.MySQLGetDelay (default is 300ms) and can make the test suite noticeably slower. Consider overriding config.MySQLGetDelay/MySQLGetDelayStdDev (and optionally MySQLMutexDisabled) to near-zero in the tests (with t.Cleanup to restore) so tests stay fast.

Copilot uses AI. Check for mistakes.
Comment on lines 52 to 58
if res.StatusCode >= http.StatusBadRequest {
body, err := io.ReadAll(res.Body)
if err != nil {
return err
}
return errors.New(string(body))
return httperr.NewHTTPError(res.StatusCode, string(body))
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The response body from http.Error typically already ends with a newline; wrapping it directly into an HTTPError and later re-emitting it via http.Error can lead to double newlines in the propagated message. Consider trimming whitespace (e.g., strings.TrimSpace) when constructing the HTTPError message.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Frontend service returns 500 for invalid customer ID instead of 400

2 participants