The `InvalidCharError` from Python's filename sanitizer libraries is a precise error — it fires when a filename string contains a character that the target operating system forbids. But the cause is almost always the same: a filename arrived from user input, a file upload, or an external API without being validated first. This guide explains exactly which characters trigger the error on each OS, how to fix it, and how to build sanitization into your code so it never reaches production.
What is FilenameSanitizer?
`FilenameSanitizer` refers to Python libraries — most commonly `python-filenamesanitizer` and similar packages — that validate and clean filename strings before they are used in filesystem operations. These libraries check the proposed filename against the rules of the target operating system and either return a sanitized version or raise an exception when a character cannot be safely replaced.
Why filename sanitization is necessary
Filenames that come from external sources — user uploads, API responses, scraped data, database records — frequently contain characters that are perfectly valid in the source context but illegal on the destination filesystem. A filename like `report: Q1/2026.pdf` is a reasonable human label, but it contains `:` and `/` — both illegal on Windows. Without sanitization, the `open()` call raises an `OSError` or the file is silently truncated at the illegal character.
What InvalidCharError means
`InvalidCharError` is the specific exception raised when a filename contains a character that the library cannot automatically replace or strip — or when the library is configured to raise rather than auto-fix. The exception message includes the original filename and the offending character, which gives you everything you need to fix it. If you are seeing this error without a clear traceback, paste the full stack trace into the Python Traceback Explainer for a plain-English breakdown of the root cause.
Note
What triggers InvalidCharError?
The error fires when the filename string contains one or more characters that the sanitizer's rule set marks as illegal. The most common triggers fall into four categories, each with a different fix path.
- Windows path separator characters — `:` (colon), `\` (backslash), `/` (forward slash); these appear frequently in timestamps and URL paths used as filenames
- Shell-reserved characters — `|`, `<`, `>`, `?`, `*`, `"` — common in filenames generated from search queries, titles, or document names
- Null bytes and control characters — Unicode codepoints U+0000 to U+001F; sometimes injected by malicious input or encoding corruption
- Windows reserved device names — CON, PRN, AUX, NUL, COM1–COM9, LPT1–LPT9 — illegal as filenames regardless of extension on Windows
The timestamp problem
The single most common source of `InvalidCharError` in real applications is a filename constructed from a timestamp. An ISO 8601 datetime like `2026-06-11T14:30:00` contains a colon — illegal on Windows. Any code that generates filenames like `backup_2026-06-11T14:30:00.zip` will fail on Windows but silently succeed on Linux, creating a subtle cross-platform bug. Replace colons in timestamps with hyphens or dots: `2026-06-11T14-30-00`.
The user input problem
When users name files in a web interface or upload files from their devices, the names arrive without any guarantee of validity. A PDF named `Invoice: Client/Project Q4.pdf` is a completely natural human-written name that contains three characters illegal on Windows. Always treat any filename that did not originate from your own code as untrusted input that requires sanitization before use.
Warning
Illegal characters by OS
The three major operating systems have very different rules about which characters are allowed in filenames. Understanding the differences is essential for writing portable file-handling code.
| Character | Windows | macOS | Linux |
|---|---|---|---|
| / (forward slash) | ✗ Illegal | ✗ Illegal | ✗ Illegal (path sep) |
| \ (backslash) | ✗ Illegal | ✓ Allowed | ✓ Allowed |
| : (colon) | ✗ Illegal | ✗ Legacy issue | ✓ Allowed |
| * ? " < > | (set) | ✗ Illegal | ✓ Allowed | ✓ Allowed |
| Null byte (\0) | ✗ Illegal | ✗ Illegal | ✗ Illegal |
| Control chars (0–31) | ✗ Illegal | ✗ Illegal | ✗ Illegal |
| Leading dot (.) | ✓ Allowed | Hidden file | Hidden file |
| Trailing dot or space | ✗ Illegal | ✓ Allowed | ✓ Allowed |
| Reserved names (CON etc.) | ✗ Illegal | ✓ Allowed | ✓ Allowed |
For cross-platform code that must work on all three systems, the safe rule is to treat Windows rules as the minimum — any character illegal on Windows should be sanitized regardless of the actual runtime OS. This gives you portable filenames that work everywhere. The Filename Sanitizer for Cross-Platform Uploads validates against all three OS rule sets simultaneously so you can check any filename in a single pass.
How to fix the error
Fixing an `InvalidCharError` always involves the same workflow: find the source of the filename, apply sanitization before the filesystem call, and verify the result. Work through these steps in order.
Read the full traceback to identify the offending character
The `InvalidCharError` message includes both the original filename string and the specific character that was rejected. Copy the full traceback and note the character. If the character is a control character or null byte, it may not be visible in the error output — use `repr()` on the filename string in your code to see the escaped representation and identify the hidden characters.
Locate where the filename originates in your code
Trace the filename back to its source using the call stack in the traceback. Common sources: the `filename` field from a multipart upload, a string constructed from user-provided metadata, an API response field, a database column, or an external file listing. The fix location is always at the source — not at the point where the error is raised.
Apply sanitization at the input boundary
Add a sanitization pass immediately after the filename enters your system — at the upload handler, the API response parser, or wherever external data first becomes a filename. Use `re.sub(r'[<>:"/\\|?*\x00-\x1F]', '-', name)` as a baseline replacement, then strip trailing dots and spaces, check against reserved Windows names, and truncate to 255 bytes. Use the Python Syntax Validator to check your sanitizer function for any syntax errors before deploying.
Validate the sanitized filename before the filesystem call
After sanitization, validate the result with the Filename Sanitizer for Cross-Platform Uploads to confirm no illegal characters remain, the name is not a reserved Windows device name, and the length is within the 255-byte limit. This catches edge cases that simple regex substitution misses — like a filename that is entirely composed of spaces after stripping, which becomes empty after trimming.
Filename Sanitizer for Cross-Platform Uploads
Paste any filename and validate it against Windows, macOS, and Linux rules simultaneously — identifies illegal characters, reserved names, length issues, and provides the clean safe version.
Sanitizing filenames manually in Python
If you prefer not to depend on a third-party library, you can implement a robust filename sanitizer in pure Python. The approach covers all Windows and cross-platform restrictions without any external dependencies.
The core sanitization logic
A complete Python filename sanitizer needs five operations applied in sequence: normalize Unicode to composed form (NFC) so characters like accented letters are stored as single code points; replace all Windows-illegal characters and ASCII control characters with a safe substitute; strip leading and trailing dots, spaces, and hyphens which are problematic on Windows; check against the list of Windows reserved device names and append a suffix if matched; and finally truncate to 255 bytes when encoded as UTF-8.
Handling Unicode filenames
Modern applications routinely handle filenames containing non-ASCII characters — Arabic, Chinese, Japanese, accented Latin characters. These are all legal on modern filesystems (NTFS, APFS, ext4) but can cause issues when encoding conversions happen. A filename that is valid UTF-8 may become corrupt if the filesystem or OS is configured for a legacy encoding like Latin-1 or Windows-1252. If you encounter filenames with garbled characters, run them through the Unicode and Encoding Repair Tool to identify and fix the encoding problem before sanitization.
When to raise vs. when to auto-fix
You have two choices when an illegal character is found: raise an exception (the `python-filenamesanitizer` library's default) or auto-replace with a safe character. For upload handlers, auto-replacement is usually the right choice — silently cleaning `invoice: Q1.pdf` to `invoice- Q1.pdf` is better than failing the upload. For internal code that generates its own filenames, raising is better — an `InvalidCharError` in your own code is a bug to fix, not an edge case to handle silently.
Tip
Cross-platform filename best practices
The most reliable filename sanitization strategy is a set of consistent rules applied at every input boundary, rather than a series of ad-hoc fixes that grow over time. These practices prevent `InvalidCharError` and its relatives from appearing in the first place.
Construct filenames from safe components
Wherever possible, generate filenames from controlled inputs rather than passing user-provided strings directly. Build filenames from sanitized identifiers, UUIDs, or timestamps with colons replaced: a UUID like `550e8400-e29b-41d4-a716-446655440000` is already safe on all platforms. If a human-readable name is required, sanitize it first and then append the safe identifier as a suffix to guarantee uniqueness.
Validate at every OS boundary
- File uploads — sanitize the uploaded filename before saving, even if your web framework provides a filename field
- API responses — treat any filename field from an external API as untrusted; validate before using
- Database records — filenames stored in a database may have been saved before your sanitization rules were in place
- Configuration files — filenames read from config files can be incorrect if the config was edited by a user
- Command-line arguments — user-supplied path arguments may contain shell expansions or special characters
Test on all target platforms
A filename bug that only manifests on Windows is invisible in a Linux-only development environment. If your application will run on Windows, test your file handling code on Windows — or add a CI job that runs on a Windows runner. The Filename Sanitizer for Cross-Platform Uploads provides an OS-agnostic check you can run from any platform, making it a practical substitute for multi-OS testing during development.
Warning
Validating filenames before use
A sanitizer that auto-replaces characters is a production safeguard. A validator that checks and reports issues is a development and debugging tool. Both have their place, and using them together gives you the strongest coverage.
What the Filename Sanitizer tool checks
The Filename Sanitizer for Cross-Platform Uploads validates filenames against all three major OS rule sets in one pass. It checks for illegal characters (Windows, macOS, Linux), Windows reserved device names, trailing dots and spaces (illegal on Windows), leading dots (hidden file signal on Unix), null bytes and control characters, and filename length in both characters and UTF-8 bytes. It also shows you the sanitized safe version of the filename alongside the validation report.
Integrating validation into CI
For applications that generate filenames from templates or configurable patterns, add a unit test that validates the generated names against cross-platform rules on every build. A filename template that works in your current environment can produce an `InvalidCharError` after a configuration change that introduces a colon into the pattern. Catching this in CI is significantly less costly than debugging it in production.
Key takeaways
- `InvalidCharError` fires when a filename contains a character illegal on the target OS — the error message always identifies the specific character.
- Windows forbids `< > : " / \ | ? *`, control characters, trailing dots/spaces, and reserved names (CON, NUL, COM1-9, LPT1-9).
- Linux only forbids null bytes and forward slashes — but portable code should apply Windows rules universally.
- Always sanitize filenames at the input boundary (upload handler, API parser) rather than catching exceptions after the fact.
- Use the Filename Sanitizer for Cross-Platform Uploads to validate any filename against all three OS rule sets in one pass.
- Unicode filenames with encoding corruption need the Unicode and Encoding Repair Tool before sanitization.
- Auto-replace illegal characters with hyphens in upload handlers; raise exceptions in internal code where invalid filenames are a bug to fix.