octobercms/october · error · ApplicationException
system::lang.media.invalid_path_encoding
Error message
system::lang.media.invalid_path_encoding
What it means
MediaLibrary::validatePath() normalizes a path and then requires it to be valid UTF-8: mb_check_encoding($path, 'UTF-8') must pass. A byte string in another encoding (Latin-1/Windows-1252 0xE9 for 'é', GBK multibyte, raw binary) triggers invalid_path_encoding, with the offending path scrubbed via mb_scrub for safe display. This guard exists because every later regex uses the /u modifier, which fails on invalid UTF-8, and storage backends assume UTF-8 keys.
Source
Thrown at modules/media/classes/MediaLibrary.php:495
* validatePath checks if file path doesn't contain any substrings that would pose a security
* threat. Returns a normalized path. Throws an exception if the path is not valid. An option
* is provided, if only normalization is needed without validation.
* @param string $path
* @param bool $normalizeOnly
* @return string
*/
public static function validatePath($path, $normalizeOnly = false): string
{
$path = str_replace('\\', '/', $path);
$path = '/'.trim($path, '/');
if ($normalizeOnly) {
return $path;
}
// Reject paths that are not valid UTF-8
if (!mb_check_encoding($path, 'UTF-8')) {
throw new ApplicationException(Lang::get('system::lang.media.invalid_path_encoding', ['path' => mb_scrub($path)]));
}
// Reject control, format and other invisible characters
if (preg_match('/[\p{C}]/u', $path)) {
throw new ApplicationException(Lang::get('system::lang.media.invalid_path', compact('path')));
}
// Reject characters reserved by file systems and URLs
if (preg_match('/[<>:"|?*]/', $path)) {
throw new ApplicationException(Lang::get('system::lang.media.invalid_path', compact('path')));
}
$regexDirectorySeparator = preg_quote('/', '#');
$regexDot = preg_quote('.', '#');
$regex = [
// Beginning of path
'(^'.$regexDot.'+?'.$regexDirectorySeparator.')',
View on GitHub (pinned to b608633a7e)
Solutions
- Convert the encoding before calling the API: $path = mb_convert_encoding($path, 'UTF-8', 'Windows-1252'); (or iconv with //TRANSLIT)
- Fix the source of the path: make DB columns utf8mb4 and store/emit UTF-8 everywhere
- For display of already-corrupt data, pass mb_scrub($path) so invalid sequences are substituted instead of crashing
Example fix
// before — $path came from a latin1 source $clean = MediaLibrary::validatePath($path); // throws invalid_path_encoding // after — convert first, then validate $clean = MediaLibrary::validatePath(mb_convert_encoding($path, 'UTF-8', 'Windows-1252'));
Defensive patterns
Strategy: type-guard
Type guard
function isUtf8Path(mixed $path): bool {
return is_string($path) && mb_check_encoding($path, 'UTF-8');
}
// usage
if (!isUtf8Path($path)) {
$path = mb_convert_encoding($path, 'UTF-8', 'Windows-1252');
} Try / catch
try {
$clean = MediaLibrary::validatePath($path);
} catch (ApplicationException $e) {
// invalid_path_encoding vs invalid_path can be distinguished by message
$path = mb_scrub($path);
$clean = MediaLibrary::validatePath($path);
} Prevention
- Standardize on UTF-8 end to end: DB columns utf8mb4, API charset UTF-8
- Convert legacy-encoded filenames at the boundary with mb_convert_encoding before any media call
- Never pass raw bytes from external systems into path APIs
When it happens
Trigger: Calling a media API with a Windows-1252-encoded filename from a legacy integration; paths read from an old latin1 database column; a client percent-decoding URL-encoded bytes into non-UTF-8 sequences; binary garbage in a crafted request.
Common situations: Migrating media indexes from old systems; scripts that read filenames from a legacy filesystem without iconv; API consumers defaulting to a single-byte charset.
Related errors
- system::lang.media.invalid_path
- editor::lang.filesystem.invalid_path
- backend::lang.media.type_blocked
- Media tags can only be processed for front-end requests.
- Invalid input data
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/3b7e23c2c1f08d21.
Report an issue: GitHub.