twigphp/Twig · error · RuntimeError

The "replace" filter expects a sequence or a mapping, got

Error message

The "replace" filter expects a sequence or a mapping, got "%s".

What it means

The Twig `replace` filter calls CoreExtension::replace, which requires the second argument (`from`) to be iterable — a sequence (array) or a mapping of search=>replace pairs, passed to strtr(). If the argument is a scalar, null, or object that is not Traversable/Array, a Twig\Error::RuntimeError is thrown naming the actual PHP debug type.

Solutions

  1. Make the second argument an array or mapping, e.g. {{ 'a-b'|replace({'-': '_'}) }}.
  2. Dump the variable ({{ dump(x) }}) and check its debug type in the message to find where it became non-iterable.
  3. If the value may be null, default it first: {{ 'abc'|replace(x|default({})) }}.
  4. Cast Traversable to array with iterator_to_array or the |column/filter family when appropriate before replacing.

Example fix

// before (template)
{{ 'hello world'|replace(' ') }}

// after
{{ 'hello world'|replace({' ': '_'}) }}
Defensive patterns

Strategy: validation

Validate before calling

// Twig template
{% if x is iterable %}{{ str|replace(x) }}{% else %}{{ str }}{% endif %}

// PHP before calling the filter
echo \is_iterable($from) ? \Twig\Extension\CoreExtension::replace($str, $from) : $str;

Type guard

function isReplaceSource($v): bool { return \is_iterable($v); }

Try / catch

try {
    $out = \Twig\Extension\CoreExtension::replace($str, $from);
} catch (\Twig\Error\RuntimeError $e) {
    $out = $str; // or log and rethrow
}

Prevention

When it happens

Trigger: Calling {{ 'abc'|replace(x) }} where x is a string, integer, boolean, null, or a non-Traversable object instead of an array or Traversable; also when a variable that was expected to be an array is actually null (e.g. missing context var or a function returning null).

Common situations: Passing a plain string like {{ 'a-b'|replace('-': '_') }}-style mistakes with wrong filter syntax; passing null because an upstream variable was unset; passing an stdClass result from json_decode without assoc=true; assuming another filter (e.g. split) returned an array but it returned null on failure.

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/b46735ce02aeaf19. Report an issue: GitHub.

Appendix: source

Thrown at src/Extension/CoreExtension.php:652

        if (false !== $timezone) {
            $date->setTimezone($timezone);
        }

        return $date;
    }

    /**
     * Replaces strings within a string.
     *
     * @param string|null        $str  String to replace in
     * @param array|\Traversable $from Replace values
     *
     * @internal
     */
    public static function replace($str, $from): string
    {
        if (!is_iterable($from)) {
            throw new RuntimeError(\sprintf('The "replace" filter expects a sequence or a mapping, got "%s".', get_debug_type($from)));
        }

        return strtr($str ?? '', self::toArray($from));
    }

    /**
     * Rounds a number.
     *
     * @param int|float|string|null   $value     The value to round
     * @param int|float               $precision The rounding precision
     * @param 'common'|'ceil'|'floor' $method    The method to use for rounding
     *
     * @return float The rounded number
     *
     * @internal
     */
    public static function round($value, $precision = 0, $method = 'common')
    {

View on GitHub (pinned to a414c3a491)