symfony/http-foundation · error · InvalidArgumentException
The filename fallback cannot contain the "%" character.
Error message
The filename fallback cannot contain the "%" character.
What it means
Percent characters are rejected in $filenameFallback because '%' is not safe in HTTP headers — it could be confused with percent-encoding (RFC 2047/5987 escape sequences) and manipulated, so makeDisposition() throws this InvalidArgumentException when the fallback contains '%'.
Solutions
- Remove or replace '%' in the fallback, e.g. str_replace('%', '', $fallback) before calling
- Do NOT pre-encode the filename — makeDisposition() rawurlencodes $filename itself for the filename* parameter
- Sanitize the fallback: preg_replace('/[^\x20-\x7e]/', '', $fallback) then strip '%','/','\\'
- Wrap in try/catch InvalidArgumentException and regenerate a sanitized fallback
Example fix
// before
$fallback = rawurlencode('résumé.pdf'); // 'r%C3%A9sum%C3%A9.pdf' → throws
HeaderUtils::makeDisposition('attachment', 'résumé.pdf', $fallback);
// after
HeaderUtils::makeDisposition('attachment', 'résumé.pdf', 'resume.pdf'); // library does the encoding Defensive patterns
Strategy: validation
Validate before calling
$filenameFallback = str_replace('%', '', $filenameFallback);
if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
$filenameFallback = 'download';
} Type guard
function isSafeFallback(string $s): bool {
return (bool) preg_match('/^[\x20-\x7e]*$/', $s) && !str_contains($s, '%');
} Try / catch
try {
$header = HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback);
} catch (\InvalidArgumentException $e) {
$header = HeaderUtils::makeDisposition($disposition, $filename, preg_replace('/[^\x20-\x7e]/', '', $filenameFallback));
} Prevention
- Never pre-urlencode filenames — the library encodes $filename itself
- Sanitize fallbacks by removing '%', '/', and '\\' before calling
- Validate user-supplied filenames against a safe-character whitelist
When it happens
Trigger: Calling makeDisposition($disposition, $filename, $filenameFallback) where $filenameFallback contains '%' — e.g. a fallback of '100% report.pdf', or pre-percent-encoded filenames like 'r%C3%A9sum%C3%A9.pdf' passed as the fallback.
Common situations: Developers pre-rawurlencode() the filename themselves and pass the encoded string as the fallback (double-encoding attempt); filenames containing literal '%' from user uploads (e.g. '50% off.pdf') without sanitizing the fallback.
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
- The disposition must be either
- The filename fallback must only contain ASCII characters.
- The filename and the fallback cannot contain the "/" and…
- The "sameSite" parameter value is not valid.
- The cookie name " " uses a reserved prefix, which requires…
AI-assisted analysis of symfony/http-foundation@5aea19cd67 (2026-09-13).
Data as JSON: /api/errors/0dc94e1d5ec5281d.
Report an issue: GitHub.
Appendix: source
Thrown at HeaderUtils.php:182
*/
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, ';');
}
/**
* Like parse_str(), but preserves dots in variable names.
*/View on GitHub (pinned to 5aea19cd67)