SigNoz/signoz · error · errors.Error
CodeForbidden
CodeForbidden
Error message
saml: expired saml response
What it means
parseMetricsTime in SigNoz's parser.go accepts epoch nanoseconds (float seconds), epoch seconds, or an RFC3339(9) string; if none parse, it returns 'cannot parse %q to a valid timestamp'. It is the parameter parser for the time= field of instant and query_range metrics API requests.
Source
Thrown at ee/authn/callbackauthn/samlcallbackauthn/authn.go:96
if err != nil {
return nil, err
}
assertionInfo, err := sp.RetrieveAssertionInfo(formValues.Get("SAMLResponse"))
if err != nil {
if errors.As(err, &saml2.ErrVerification{}) {
return nil, errors.New(errors.TypeForbidden, errors.CodeForbidden, err.Error())
}
if errors.As(err, &saml2.ErrMissingElement{}) {
return nil, errors.New(errors.TypeNotFound, errors.CodeNotFound, err.Error())
}
return nil, err
}
if assertionInfo.WarningInfo.InvalidTime {
return nil, errors.New(errors.TypeForbidden, errors.CodeForbidden, "saml: expired saml response")
}
email, err := valuer.NewEmail(assertionInfo.NameID)
if err != nil {
return nil, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "saml: invalid email").WithAdditional("The nameID assertion is used to retrieve the email address, please check your IDP configuration and try again.")
}
name := ""
if nameAttribute := samlConfig.AttributeMapping.Name; nameAttribute != "" {
if val := assertionInfo.Values.Get(nameAttribute); val != "" {
name = val
}
}
var groups []string
if groupAttribute := samlConfig.AttributeMapping.Groups; groupAttribute != "" {
groups = assertionInfo.Values.GetAll(groupAttribute)
}View on GitHub (pinned to 5069bf80b0)
Solutions
- Send time as RFC3339Nano (e.g. 2024-01-01T00:00:00Z) or as epoch seconds/nanoseconds
- Validate the timestamp client-side with the same three strategies (ParseFloat, integer epoch, time.Parse(time.RFC3339Nano)) before issuing the request
- If you need Prometheus-style relative times like '5m', compute and send the absolute epoch instead
Example fix
# before curl '.../api/v1/query?time=2024-01-01 00:00:00' # after curl '.../api/v1/query?time=2024-01-01T00:00:00Z'
Defensive patterns
Strategy: validation
Validate before calling
func validMetricsTime(s string) bool {
if _, err := strconv.ParseFloat(s, 64); err == nil { return true }
if _, err := time.Parse(time.RFC3339Nano, s); err == nil { return true }
return false
}
if !validMetricsTime(timeStr) { /* fix before sending */ } Type guard
null
Try / catch
// client side (Go)
if _, err := time.Parse(time.RFC3339Nano, s); err != nil {
s = time.Now().UTC().Format(time.RFC3339Nano)
} Prevention
- Standardize on RFC3339 with 'T' separator or epoch seconds
- Never send space-separated datetimes
- Add client-side parsing tests mirroring the server's three strategies
When it happens
Trigger: Calling /api/v1/query or /api/v1/query_range (or parseInstantQueryMetricsRequest/parseQueryRangeRequest) with a time value that is neither a plain float/integer epoch nor RFC3339Nano — e.g. '2024-01-01 00:00' (space instead of T), '1h-ago', an empty-derived default, or a locale-formatted date.
Common situations: Frontends sending moment.js date-fns formatted strings instead of ISO-8601 with 'T'; shell scripts passing relative durations expecting Prometheus syntax; timezone offsets written as '+05:30' with a space separator; migrations from the Prometheus API which allows more formats.
Related errors
AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28).
Data as JSON: /api/errors/d6e942f5ab81806d.
Report an issue: GitHub.