symfony/http-foundation · error · InvalidArgumentException

The filename fallback must only contain ASCII characters.

Error message

The filename fallback must only contain ASCII characters.

What it means

In makeDisposition(), the $filenameFallback (which defaults to $filename when empty) is checked with preg_match('/^[\x20-\x7e]*$/') to ensure it contains only printable ASCII characters. The fallback goes into the header verbatim, so non-ASCII bytes would produce a malformed/invalid header; hence the InvalidArgumentException.

Solutions

  1. Pass an ASCII-only third argument as $filenameFallback, e.g. HeaderUtils::makeDisposition($d, 'ünïcode.pdf', 'unicode.pdf')
  2. Transliterate the filename first (iconv with //TRANSLIT or a slugifier) to produce an ASCII fallback
  3. Strip or replace non-ASCII bytes with a fallback like preg_replace('/[^\x20-\x7e]/', '_', $name)
  4. Wrap in try/catch and fall back to a generic ASCII filename like 'download'

Example fix

// before
HeaderUtils::makeDisposition('attachment', 'naïve file.pdf'); // throws
// after
HeaderUtils::makeDisposition('attachment', 'naïve file.pdf', 'naive file.pdf');
Defensive patterns

Strategy: validation

Validate before calling

if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
    $filenameFallback = iconv('UTF-8', 'ASCII//TRANSLIT', $filenameFallback) ?: 'download';
}

Type guard

function isAsciiPrintable(string $s): bool {
    return (bool) preg_match('/^[\x20-\x7e]*$/', $s);
}

Try / catch

try {
    $header = HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback);
} catch (\InvalidArgumentException $e) {
    $header = HeaderUtils::makeDisposition($disposition, $filename, 'download');
}

Prevention

When it happens

Trigger: Calling makeDisposition($disposition, $filename) where $filename (used as implicit fallback) contains UTF-8/multibyte characters like 'ünïcode.pdf' or '日本語.pdf' and no ASCII-only $filenameFallback is supplied; or explicitly passing a non-ASCII $filenameFallback.

Common situations: Serving files with accented, Cyrillic, CJK or emoji names without providing an ASCII fallback; user-uploaded filenames with non-ASCII characters passed directly to makeDisposition; ISO-8859-1 encoded strings treated as ASCII.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of symfony/http-foundation@5aea19cd67 (2026-09-13). Data as JSON: /api/errors/80ac7bdf190b53d8. Report an issue: GitHub.

Appendix: source

Thrown at HeaderUtils.php:177

     *                                 it can be omitted, or just copied from $filename
     *
     * @throws \InvalidArgumentException
     *
     * @see RFC 6266
     */
    public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string
    {
        if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE], true)) {
            throw new \InvalidArgumentException(\sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
        }

        if ('' === $filenameFallback) {
            $filenameFallback = $filename;
        }

        // filenameFallback is not ASCII.
        if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
            throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
        }

        // percent characters aren't safe in fallback.
        if (str_contains($filenameFallback, '%')) {
            throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
        }

        // path separators aren't allowed in either.
        if (str_contains($filename, '/') || str_contains($filename, '\\') || str_contains($filenameFallback, '/') || str_contains($filenameFallback, '\\')) {
            throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
        }

        $params = ['filename' => $filenameFallback];
        if ($filename !== $filenameFallback) {
            $params['filename*'] = "utf-8''".rawurlencode($filename);
        }

        return $disposition.'; '.self::toString($params, ';');

View on GitHub (pinned to 5aea19cd67)