dgraph-io/dgraph · error

invalid untilDate

Error message

invalid untilDate %q: %v

What it means

This error is thrown by buildBackupDateFilter in the Dgraph admin GraphQL API when the untilDate argument passed to the listBackups query cannot be parsed into a valid date/time. parseGraphQLDate is strict: it accepts a plain date (YYYY-MM-DD), a full RFC3339 datetime containing 'T', or a Unix timestamp, and any other format fails. The original parse error is embedded so the developer can see exactly which format check failed.

Solutions

  1. Reformat untilDate as RFC3339, e.g. '2024-03-15T10:00:00Z', or as a plain date '2024-03-15'.
  2. If passing a timestamp, send a Unix timestamp (integer string) which parseGraphQLDate accepts.
  3. Check the embedded %v error in the message to see exactly which parse stage failed and correct that specific part.
  4. Validate the string client-side with time.Parse(time.RFC3339, s) or new Date(value) before sending.
  5. If the input comes from a config or CLI flag, echo and fix the raw value; look for stray whitespace or quotes.

Example fix

// before
{ listBackups(input: { location: "s3://bucket", untilDate: "03/15/2024" }) }
// after
{ listBackups(input: { location: "s3://bucket", untilDate: "2024-03-15" }) }
Defensive patterns

Strategy: validation

Validate before calling

const RFC3339 = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2}))?$/;
function isValidUntilDate(s) {
  if (!RFC3339.test(s)) return false;
  return !isNaN(new Date(s).getTime());
}
// pass only if isValidUntilDate(untilDate)

Type guard

function isRFC3339OrDate(s) {
  return typeof s === 'string' && (/^\d{4}-\d{2}-\d{2}$/.test(s) || !isNaN(Date.parse(s)) && s.includes('T'));
}

Try / catch

try {
  await listBackups({ untilDate });
} catch (e) {
  if (String(e.message).includes('invalid untilDate')) {
    // fall back to a plain YYYY-MM-DD or RFC3339 reformatted value and retry once
  }
}

Prevention

When it happens

Trigger: Calling the admin GraphQL listBackups mutation/query with untilDate set to a string that parseGraphQLDate rejects: e.g. '03/15/2024', '15-03-2024', 'yesterday', '2024/03/15', or a truncated datetime missing timezone like '2024-03-15T10:00'.

Common situations: Developers pass human-friendly dates or locale-formatted strings (US MM/DD/YYYY), omit the 'T'/timezone in RFC3339 timestamps, or pass values produced by non-Go date formatters with different separators. Frontends that format Date objects with toLocaleString are a frequent source.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/61ea42c58ac88f67. Report an issue: GitHub.

Appendix: source

Thrown at graphql/admin/list_backups.go:87

	}
	if input.LastNDays > 0 && input.SinceDate != "" {
		return filter, errors.Errorf("lastNDays and sinceDate are mutually exclusive")
	}
	if input.LastNDays > 0 {
		since := time.Now().UTC().AddDate(0, 0, -input.LastNDays).Truncate(24 * time.Hour)
		filter.Since = &since
	}
	if input.SinceDate != "" {
		t, err := parseGraphQLDate(input.SinceDate)
		if err != nil {
			return filter, errors.Errorf("invalid sinceDate %q: %v", input.SinceDate, err)
		}
		filter.Since = &t
	}
	if input.UntilDate != "" {
		t, err := parseGraphQLDate(input.UntilDate)
		if err != nil {
			return filter, errors.Errorf("invalid untilDate %q: %v", input.UntilDate, err)
		}
		var end time.Time
		if strings.Contains(input.UntilDate, "T") {
			// RFC3339 datetime: user gave an exact timestamp, respect it.
			end = t
		} else {
			// Plain date (YYYY-MM-DD): extend to end of that calendar day.
			end = t.Add(24*time.Hour - time.Millisecond)
		}
		filter.Until = &end
	}
	return filter, nil
}

// needsFullManifest returns true when the full manifest.json must be read.
// It is true when the caller explicitly sets fullManifest OR when the query
// selection set includes "groups", so existing queries that request groups
// continue to receive populated data without any input change.

View on GitHub (pinned to 759e242be6)