twigphp/Twig · error · Twig\Error\RuntimeError

Unable to format the given date.

Error message

Unable to format the given date.

What it means

formatDateTime() (used internally by formatDate/formatTime) wraps IntlDateFormatter::format(); a false return means ICU could not render the date for the given pattern/calendar/locale, so the extension throws this RuntimeError.

Solutions

  1. Convert input to a DateTimeInterface first: new DateTimeImmutable($value) inside a validity check.
  2. Filter out legacy sentinel dates like '0000-00-00' before formatting.
  3. Validate the $pattern is a valid ICU date/time pattern.
  4. Check installed ICU data (php --ri intl) for the target locale/calendar.

Example fix

// before
{{ row.birthday|format_date('short') }}
// after
{% if row.birthday and row.birthday != '0000-00-00' %}{{ row.birthday|date('Y-m-d')|format_date('short') }}{% endif %}
Defensive patterns

Strategy: validation

Validate before calling

try { $date = $date instanceof \DateTimeInterface ? $date : new \DateTimeImmutable((string)$date); } catch (\Exception $e) { /* skip formatting */ }

Type guard

function isFormattableDate(mixed $d): bool { try { return $d instanceof \DateTimeInterface || (is_string($d) && '' !== $d && false !== strtotime($d)); } catch (\Exception) { return false; } }

Try / catch

try { $s = format_date($value, 'short'); } catch (Twig\Error\RuntimeError $e) { $s = '—'; }

Prevention

When it happens

Trigger: Formatting values that are not valid date/time inputs (empty string, invalid date strings), or incompatible pattern/calendar combinations (e.g. a pattern with non-Gregorian calendar), or a DateTimeImmutable/IntlDateFormatter mismatch via weird timezone data.

Common situations: '0000-00-00' legacy database dates passed straight to the filter; invalid user input; missing ICU locale data; pattern strings containing ICU-unsupported characters.

Related errors


AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13). Data as JSON: /api/errors/e1ec41adcf3a3e0b. Report an issue: GitHub.

Appendix: source

Thrown at extra/intl-extra/IntlExtension.php:421

    /**
     * @param \DateTimeInterface|string|null  $date     A date or null to use the current time
     * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
     */
    public function formatDateTime(Environment $env, $date, ?string $dateFormat = null, ?string $timeFormat = null, string $pattern = '', $timezone = null, ?string $calendar = null, ?string $locale = null): string
    {
        $date = $env->getExtension(CoreExtension::class)->convertDate($date, $timezone);

        $formatterTimezone = $timezone;
        if (null === $formatterTimezone || false === $formatterTimezone) {
            $formatterTimezone = $date->getTimezone();
        } elseif (\is_string($formatterTimezone)) {
            $formatterTimezone = new \DateTimeZone($timezone);
        }
        $formatter = $this->createDateFormatter($locale, $dateFormat, $timeFormat, $pattern, $formatterTimezone, $calendar);

        if (false === $ret = $formatter->format($date)) {
            throw new RuntimeError('Unable to format the given date.');
        }

        return $ret;
    }

    /**
     * @param \DateTimeInterface|string|null  $date     A date or null to use the current time
     * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
     */
    public function formatDate(Environment $env, $date, ?string $dateFormat = null, string $pattern = '', $timezone = null, ?string $calendar = null, ?string $locale = null): string
    {
        return $this->formatDateTime($env, $date, $dateFormat, 'none', $pattern, $timezone, $calendar, $locale);
    }

    /**
     * @param \DateTimeInterface|string|null  $date     A date or null to use the current time
     * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
     */

View on GitHub (pinned to a414c3a491)