SigNoz/signoz · error · model.ApiError

ErrorBadData

ErrorBadData

Error message

ErrorID missing from params

What it means

GetNextPrevErrorIDs validates its input and rejects the call with ErrorBadData when queryParams.ErrorID is an empty string. This is a client-side argument validation error raised before any SQL is issued, so it always indicates a malformed or incomplete API request rather than a backend problem.

Source

Thrown at pkg/query-service/app/clickhouseReader/reader.go:2398

	if err != nil {
		r.logger.Error("Error in processing sql query", errorsV2.Attr(err))
		return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
	}

	if len(getErrorWithSpanReponse) > 0 {
		return &getErrorWithSpanReponse[0], nil
	} else {
		return nil, &model.ApiError{Typ: model.ErrorNotFound, Err: fmt.Errorf("Error/Exception not found")}
	}

}

func (r *ClickHouseReader) GetNextPrevErrorIDs(ctx context.Context, queryParams *model.GetErrorParams) (*model.NextPrevErrorIDs, *model.ApiError) {

	if queryParams.ErrorID == "" {
		r.logger.Error("errorId missing from params")
		return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("ErrorID missing from params")}
	}
	var apiErr *model.ApiError
	getNextPrevErrorIDsResponse := model.NextPrevErrorIDs{
		GroupID: queryParams.GroupID,
	}
	getNextPrevErrorIDsResponse.NextErrorID, getNextPrevErrorIDsResponse.NextTimestamp, apiErr = r.getNextErrorID(ctx, queryParams)
	if apiErr != nil {
		r.logger.Error("Unable to get next error ID due to err: ", errorsV2.Attr(apiErr))
		return nil, apiErr
	}
	getNextPrevErrorIDsResponse.PrevErrorID, getNextPrevErrorIDsResponse.PrevTimestamp, apiErr = r.getPrevErrorID(ctx, queryParams)
	if apiErr != nil {
		r.logger.Error("Unable to get prev error ID due to err: ", errorsV2.Attr(apiErr))
		return nil, apiErr
	}
	return &getNextPrevErrorIDsResponse, nil

}

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Fix the caller to always supply a non-empty errorID before invoking the API
  2. Add request-level validation in the HTTP handler so a 400 is returned with a clear message instead of reaching the reader
  3. URL-encode the errorID when building links from the UI
  4. Log the incoming params at the handler boundary to find which client sends empty IDs

Example fix

// before
resp, apiErr := reader.GetNextPrevErrorIDs(ctx, queryParams)

// after
if queryParams.ErrorID == "" {
  return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("errorId is required")}
}
resp, apiErr := reader.GetNextPrevErrorIDs(ctx, queryParams)
Defensive patterns

Strategy: validation

Validate before calling

if queryParams.ErrorID == "" {
  return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("errorId is required")}
}
resp, apiErr := reader.GetNextPrevErrorIDs(ctx, queryParams)

Type guard

func hasErrorID(p *model.GetErrorParams) bool { return p != nil && strings.TrimSpace(p.ErrorID) != "" }

Try / catch

// check ApiError.Typ == model.ErrorBadData and return 400 to the client with a clear field message

Prevention

When it happens

Trigger: Calling the next/prev error navigation endpoint without an errorId query parameter, or programatically constructing model.GetErrorParams{ErrorID: ""} and passing it to GetNextPrevErrorIDs.

Common situations: Frontend navigating between error events sends an empty errorId because of a race where the detail panel loads before the selected error is set; a script iterating over a list of errors hits an entry with a missing ID; query-string parsing drops the param when it contains special characters.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/5fe42484d5ae8898. Report an issue: GitHub.