SigNoz/signoz · error

public_dashboard_invalid_input

public_dashboard_invalid_input

Error message

invalid startTime

What it means

PublicDashboard.ResolveTimeRange, when TimeRangeEnabled, parses startTimeRaw with strconv.ParseUint(base 10, 64-bit). A missing, non-numeric, negative, or overflowing start timestamp yields 'invalid startTime'. Values are epoch seconds as unsigned integers.

Source

Thrown at pkg/types/dashboardtypes/public_dashboard.go:223

func (typ *PublicDashboard) Update(timeRangeEnabled bool, defaultTimeRange string) {
	typ.TimeRangeEnabled = timeRangeEnabled
	typ.DefaultTimeRange = defaultTimeRange
	typ.UpdatedAt = time.Now()
}

func (typ *PublicDashboard) PublicPath() string {
	return "/public/dashboard/" + typ.ID.StringValue()
}

// ResolveTimeRange returns the [start, end] window in epoch millis for a public
// widget/panel query: the caller-supplied range when the dashboard allows it,
// otherwise now minus the configured default range.
func (typ *PublicDashboard) ResolveTimeRange(startTimeRaw, endTimeRaw string) (uint64, uint64, error) {
	if typ.TimeRangeEnabled {
		startTime, err := strconv.ParseUint(startTimeRaw, 10, 64)
		if err != nil {
			return 0, 0, errors.New(errors.TypeInvalidInput, ErrCodePublicDashboardInvalidInput, "invalid startTime")
		}
		endTime, err := strconv.ParseUint(endTimeRaw, 10, 64)
		if err != nil {
			return 0, 0, errors.New(errors.TypeInvalidInput, ErrCodePublicDashboardInvalidInput, "invalid endTime")
		}
		return startTime, endTime, nil
	}

	timeRange, err := time.ParseDuration(typ.DefaultTimeRange)
	if err != nil {
		return 0, 0, errors.WrapInternalf(err, errors.CodeInternal, "stored defaultTimeRange %q is not a valid duration", typ.DefaultTimeRange)
	}
	now := time.Now()
	return uint64(now.Add(-timeRange).UnixMilli()), uint64(now.UnixMilli()), nil
}

func (typ *PostablePublicDashboard) UnmarshalJSON(data []byte) error {
	type alias PostablePublicDashboard

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Send startTime as epoch seconds in decimal (e.g. 1712345678)
  2. Verify the query param name and that it's actually included in the URL
  3. Convert ISO dates: Math.floor(Date.parse(iso)/1000)
  4. Guard against NaN/negative values before building the URL

Example fix

// before
?startTime=2024-04-05T00:00:00Z
// after
?startTime=1712275200
Defensive patterns

Strategy: validation

Validate before calling

if (!/^\d{1,19}$/.test(String(startTime))) throw new Error('startTime must be epoch seconds');

Type guard

function isEpochSeconds(v: string): boolean { return /^\d{1,19}$/.test(v); }

Prevention

When it happens

Trigger: Calling the public dashboard widget range API with startTime absent, a float (1712345678.5), an ISO date string, or a value > 2^64-1 while the dashboard has time range selection enabled.

Common situations: Frontends sending ISO 8601 or milliseconds where seconds are expected; URL encoding issues dropping the param; new public dashboards enabling time range after launch.

Related errors


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