diff --git a/pkg/server/BUILD.bazel b/pkg/server/BUILD.bazel index e901b1ed8eb8..22f788aea569 100644 --- a/pkg/server/BUILD.bazel +++ b/pkg/server/BUILD.bazel @@ -219,6 +219,7 @@ go_library( "//pkg/sql/optionalnodeliveness", "//pkg/sql/parser", "//pkg/sql/pgwire", + "//pkg/sql/pgwire/pgcode", "//pkg/sql/pgwire/pgerror", "//pkg/sql/pgwire/pgwirecancel", "//pkg/sql/physicalplan", @@ -482,6 +483,8 @@ go_test( "//pkg/sql/clusterunique", "//pkg/sql/execinfrapb", "//pkg/sql/idxusage", + "//pkg/sql/pgwire/pgcode", + "//pkg/sql/pgwire/pgerror", "//pkg/sql/roleoption", "//pkg/sql/sem/catconstants", "//pkg/sql/sem/tree", diff --git a/pkg/server/admin.go b/pkg/server/admin.go index a1a07c3fa14e..13c4c604099b 100644 --- a/pkg/server/admin.go +++ b/pkg/server/admin.go @@ -51,6 +51,8 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/isql" "github.com/cockroachdb/cockroach/pkg/sql/optionalnodeliveness" "github.com/cockroachdb/cockroach/pkg/sql/parser" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" "github.com/cockroachdb/cockroach/pkg/sql/privilege" "github.com/cockroachdb/cockroach/pkg/sql/roleoption" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" @@ -109,10 +111,6 @@ func nonTableDescriptorRangeCount() int64 { })) } -// apiServerMessage is the standard body for all HTTP 500 responses. -var errAdminAPIError = grpcstatus.Errorf(codes.Internal, "An internal server error "+ - "has occurred. Please check your CockroachDB logs for more details.") - // A adminServer provides a RESTful HTTP API to administration of // the cockroach cluster. type adminServer struct { @@ -309,14 +307,30 @@ func (s *adminServer) RegisterGateway( // the RPC endpoint method. func serverError(ctx context.Context, err error) error { log.ErrorfDepth(ctx, 1, "%+v", err) - return errAdminAPIError + + // Include the PGCode in the message for easier troubleshooting + errCode := pgerror.GetPGCode(err).String() + if errCode != pgcode.Uncategorized.String() { + errMessage := fmt.Sprintf("%s Error Code: %s", errAPIInternalErrorString, errCode) + return grpcstatus.Errorf(codes.Internal, errMessage) + } + + // The error is already grpcstatus formatted error. + // Likely calling serverError multiple times on same error. + grpcCode := grpcstatus.Code(err) + if grpcCode != codes.Unknown { + return err + } + + // Fallback to generic message + return errAPIInternalError } // serverErrorf logs the provided error and returns an error that should be returned by // the RPC endpoint method. func serverErrorf(ctx context.Context, format string, args ...interface{}) error { log.ErrorfDepth(ctx, 1, format, args...) - return errAdminAPIError + return errAPIInternalError } // isNotFoundError returns true if err is a table/database not found error. diff --git a/pkg/server/admin_test.go b/pkg/server/admin_test.go index 0f6548e4e033..631b4c13173c 100644 --- a/pkg/server/admin_test.go +++ b/pkg/server/admin_test.go @@ -47,6 +47,8 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql" "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" "github.com/cockroachdb/cockroach/pkg/sql/idxusage" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" "github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants" "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" "github.com/cockroachdb/cockroach/pkg/sql/sessiondatapb" @@ -3249,6 +3251,22 @@ func TestAdminPrivilegeChecker(t *testing.T) { } } +func TestServerError(t *testing.T) { + defer leaktest.AfterTest(t)() + defer log.Scope(t).Close(t) + ctx := context.Background() + pgError := pgerror.New(pgcode.OutOfMemory, "TestServerError.OutOfMemory") + err := serverError(ctx, pgError) + require.Equal(t, "rpc error: code = Internal desc = An internal server error has occurred. Please check your CockroachDB logs for more details. Error Code: 53200", err.Error()) + + err = serverError(ctx, err) + require.Equal(t, "rpc error: code = Internal desc = An internal server error has occurred. Please check your CockroachDB logs for more details. Error Code: 53200", err.Error()) + + err = fmt.Errorf("random error that is not pgerror or grpcstatus") + err = serverError(ctx, err) + require.Equal(t, "rpc error: code = Internal desc = An internal server error has occurred. Please check your CockroachDB logs for more details.", err.Error()) +} + func TestDatabaseAndTableIndexRecommendations(t *testing.T) { defer leaktest.AfterTest(t)() defer log.Scope(t).Close(t)