SSE: Return error messages instead of 500 on SSE command parse errors (#109480)

fixes #108897

---------

Co-authored-by: Kyle Brandt <kyle@grafana.com>
This commit is contained in:
Ihor Yeromin
2025-09-02 18:00:14 +00:00
committed by GitHub
co-authored by Kyle Brandt
parent 76af73b3f3
commit bdf9583ada
4 changed files with 40 additions and 2 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ func UnmarshalMathCommand(rn *rawNode) (*MathCommand, error) {
gm, err := NewMathCommand(rn.RefID, exprString)
if err != nil {
return nil, fmt.Errorf("invalid math command type: %w", err)
return nil, fmt.Errorf("invalid math command: %w", err)
}
return gm, nil
}
+19
View File
@@ -75,6 +75,25 @@ func MakeDependencyError(refID, depRefID string) error {
return DependencyError.Build(data)
}
var parsErrStr = "failed to parse expression [{{ .Public.refId }}]: {{.Public.error}}"
var ParseError = errutil.NewBase(
errutil.StatusBadRequest, "sse.parseError").MustTemplate(
parsErrStr,
errutil.WithPublic(parsErrStr))
func MakeParseError(refID string, err error) error {
data := errutil.TemplateData{
Public: map[string]interface{}{
"refId": refID,
"error": err.Error(),
},
Error: err,
}
return ParseError.Build(data)
}
var unexpectedNodeTypeErrString = "expected executable node type but got node type [{{ .Public.nodeType }} for refid [{{ .Public.refId}}]"
var UnexpectedNodeTypeError = errutil.NewBase(
+1 -1
View File
@@ -154,7 +154,7 @@ func buildCMDNode(ctx context.Context, rn *rawNode, toggles featuremgmt.FeatureT
return nil, fmt.Errorf("expression command type '%v' in expression '%v' not implemented", commandType, rn.RefID)
}
if err != nil {
return nil, fmt.Errorf("failed to parse expression '%v': %w", rn.RefID, err)
return nil, MakeParseError(rn.RefID, err)
}
return node, nil
+19
View File
@@ -148,6 +148,25 @@ func TestDSQueryError(t *testing.T) {
require.Equal(t, fp(42), res.Responses["C"].Frames[0].Fields[0].At(0))
}
func TestParseError(t *testing.T) {
resp := map[string]backend.DataResponse{}
queries := []Query{
{
RefID: "A",
DataSource: dataSourceModel(),
JSON: json.RawMessage(`{ "datasource": { "uid": "__expr__", "type": "__expr__"}, "type": "math", "expression": "asdf" }`),
},
}
s, req := newMockQueryService(resp, queries)
_, err := s.BuildPipeline(t.Context(), req)
require.ErrorContains(t, err, "parse")
require.ErrorContains(t, err, "math")
require.ErrorContains(t, err, "asdf")
}
func TestSQLExpressionCellLimitFromConfig(t *testing.T) {
tests := []struct {
name string