symfony/polyfill-mbstring · error · ValueError

(dynamic: errorFormat passed to assertEncoding, e.g…

Error message

%s (dynamic: errorFormat passed to assertEncoding, e.g. 'mb_scrub(): Argument #2 ($encoding) must be a valid encoding, "%s" given')

What it means

assertEncoding() is the polyfill's internal validator: it calls mb_check_encoding and, when the encoding is invalid, throws a ValueError whose message is built from the caller-supplied $errorFormat with the encoding interpolated. The exact message depends on the caller, e.g. 'mb_scrub(): Argument #2 ($encoding) must be a valid encoding, "%s" given'. This is thrown whenever mb_scrub, mb_str_pad, mb_ucfirst, mb_lcfirst, or mb_internal_trim receives an unsupported encoding.

Solutions

  1. Use 'UTF-8' (the polyfill's supported encoding) or a recognized alias accepted by mb_check_encoding
  2. Validate the encoding before calling: in_array($enc, mb_list_encodings(), true) or @mb_check_encoding('', $enc)
  3. Convert data to UTF-8 first rather than requesting another encoding
  4. Catch \ValueError and fall back to the default encoding

Example fix

// before
mb_scrub($text, 'Windows-1252');
// after
mb_scrub(mb_convert_encoding($text, 'UTF-8', 'Windows-1252'), 'UTF-8');
Defensive patterns

Strategy: validation

Validate before calling

if (!@mb_check_encoding('', $encoding)) {
    $encoding = 'UTF-8';
}
mb_scrub($string, $encoding);

Type guard

function isSupportedMbEncoding(?string $encoding): bool
{
    return $encoding === null || @mb_check_encoding('', $encoding);
}

Try / catch

try {
    $result = mb_scrub($string, $encoding);
} catch (\ValueError $e) {
    $result = mb_scrub($string, 'UTF-8');
}

Prevention

When it happens

Trigger: Calling mb_scrub($s, 'ISO-8859-1'), mb_ucfirst($s, $enc), mb_lcfirst($s, $enc), or mb_internal_trim(...) with any encoding the polyfill doesn't recognize (it only truly supports UTF-8) on PHP >= 8.0; an invalid encoding returned from a getEncoding()-style default.

Common situations: Passing legacy encodings used with native ext-mbstring to the polyfill; encoding names built dynamically from user input, DB config, or HTTP headers without validation; typos like 'utf8' vs 'UTF-8' depending on the accepted alias list.

Related errors


AI-assisted analysis of symfony/polyfill-mbstring@d3d318bad5 (2026-09-13). Data as JSON: /api/errors/7d9383275dd41f29. Report an issue: GitHub.

Appendix: source

Thrown at Mbstring.php:1125

        } else {
            $characters = preg_quote($characters);
        }

        $string = preg_replace(\sprintf($regex, $characters), '', $string);

        if (null === $encoding) {
            return $string;
        }

        return self::iconv('UTF-8', $encoding, $string);
    }

    private static function assertEncoding(string $encoding, string $errorFormat): bool
    {
        try {
            $validEncoding = @self::mb_check_encoding('', $encoding);
        } catch (\ValueError $e) {
            throw new \ValueError(\sprintf($errorFormat, $encoding));
        }

        if (!$validEncoding) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(\sprintf($errorFormat, $encoding), \E_USER_WARNING);
            } else {
                throw new \ValueError(\sprintf($errorFormat, $encoding));
            }
        }

        return $validEncoding;
    }
}

View on GitHub (pinned to d3d318bad5)