twigphp/Twig · error · Twig\Error\RuntimeError

Unable to format the given number.

Error message

Unable to format the given number.

What it means

formatNumber() wraps NumberFormatter::format(); when it returns false — ICU could not format the given number for the requested style/locale — the extension throws this RuntimeError instead of outputting an empty/false value.

Solutions

  1. Coerce to int/float and validate is_numeric($number) before formatting.
  2. Check for NAN/INF with is_finite().
  3. Simplify or remove custom $attrs that may break the formatter.
  4. Verify the intl extension and ICU data are available (php --ri intl).

Example fix

// before
{{ userInput|format_number }}
// after
{% if userInput is numeric %}{{ userInput|format_number }}{% else %}—{% endif %}
Defensive patterns

Strategy: validation

Validate before calling

if (!is_numeric($number) || !is_finite((float)$number)) { throw new \InvalidArgumentException('Number required'); }

Type guard

function isFormattableNumber(mixed $n): bool { return (is_int($n) || is_float($n)) && is_finite($n); }

Try / catch

try { $s = format_number($number, attrs: $attrs); } catch (Twig\Error\RuntimeError $e) { $s = (string) (float) $number; }

Prevention

When it happens

Trigger: Calling format_number() with a non-numeric value (NaN, INF, non-numeric string), or incompatible attrs/locale causing the formatter to fail.

Common situations: Passing null or user input that is not numeric; locale data missing in ICU; using scientific/ordinal styles with inputs ICU rejects (e.g. spelling-out with unsupported locales).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

        $formatter = $this->createNumberFormatter($locale, 'currency', $attrs);

        if (false === $ret = $formatter->formatCurrency($amount, $currency)) {
            throw new RuntimeError('Unable to format the given number as a currency.');
        }

        return $ret;
    }

    public function formatNumber($number, array $attrs = [], string $style = 'decimal', string $type = 'default', ?string $locale = null): string
    {
        if (!isset(self::NUMBER_TYPES[$type])) {
            throw new RuntimeError(\sprintf('The type "%s" does not exist, known types are: "%s".', $type, implode('", "', array_keys(self::NUMBER_TYPES))));
        }

        $formatter = $this->createNumberFormatter($locale, $style, $attrs);

        if (false === $ret = $formatter->format($number, self::NUMBER_TYPES[$type])) {
            throw new RuntimeError('Unable to format the given number.');
        }

        return $ret;
    }

    public function formatNumberStyle(string $style, $number, array $attrs = [], string $type = 'default', ?string $locale = null): string
    {
        return $this->formatNumber($number, $attrs, $style, $type, $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
     */
    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);

View on GitHub (pinned to a414c3a491)