badges/shields · error · InvalidResponse

invalid date

Error message

invalid date

What it means

The shared date utility throws InvalidResponse with prettyMessage 'invalid date' in parseDate when dayjs cannot parse the supplied input into a valid date. It is thrown for any badge service that passes an unparsable date string (or a date failing the strict format check) into dayjs helpers.

Source

Thrown at services/date.js:42

 * @throws {InvalidResponse} - Error if validation fails
 * @see https://day.js.org/docs/en/parse/string
 * @see https://day.js.org/docs/en/parse/string-format
 * @see https://day.js.org/docs/en/parse/is-valid
 * @example
 * parseDate('2024-01-01')
 * parseDate('31/01/2024', 'DD/MM/YYYY')
 * parseDate('2018 Enero 15', 'YYYY MMMM DD', 'es')
 */
function parseDate(...args) {
  let date
  if (args.length >= 2) {
    // always use strict mode if format arg is supplied
    date = dayjs(...args, true)
  } else {
    date = dayjs(...args)
  }
  if (!date.isValid()) {
    throw new InvalidResponse({ prettyMessage: 'invalid date' })
  }
  return date
}

/**
 * Returns a formatted date string without the year based on the value of input date param d.
 *
 * @param {Date | string | number | dayjs } d JS Date object, string, unix timestamp or dayjs object
 * @returns {string} Formatted date string
 */
function formatDate(d) {
  const date = parseDate(d)
  const dateString = date.calendar(null, {
    lastDay: '[yesterday]',
    sameDay: '[today]',
    lastWeek: '[last] dddd',
    sameElse: 'MMMM YYYY',
  })

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. Log the raw upstream value to see the actual format being passed to parseDate
  2. Parse epoch values with dayjs.unix/Number conversion before passing the string to the badge service
  3. If using the format argument, ensure the string exactly matches the strict format tokens
  4. Handle the new upstream format before calling parseDate if the upstream format changed

Example fix

// before
parseDate(String(createdAtSeconds))  // invalid date
// after
parseDate(new Date(Number(createdAtSeconds) * 1000).toISOString())
Defensive patterns

Strategy: validation

Validate before calling

function isParsableDate(v) {
  if (v == null || v === '') return false
  const d = dayjs(v)
  return d.isValid()
}

Type guard

function isValidDateString(v) {
  return typeof v === 'string' && v.length > 0 && !Number.isNaN(Date.parse(v))
}

Try / catch

try {
  const d = parseDate(input)
} catch (err) {
  if (err.prettyMessage === 'invalid date') {
    d = null // render fallback badge
  } else throw err
}

Prevention

When it happens

Trigger: An upstream API returns a date string in an unexpected format, an empty string, null, or a string not matching the supplied strict format, so dayjs(...).isValid() is false.

Common situations: Upstream changed their timestamp format (e.g. epoch seconds vs ISO 8601); localized date formats; null last_updated fields for brand-new resources; passing epoch numbers as strings.

Related errors


AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30). Data as JSON: /api/errors/55e29c9e72da0522. Report an issue: GitHub.