C# FormatException — Input string was not in a correct format
FormatException: input string format is invalid
Verified against .NET 8 documentation, int.TryParse API docs, DateTime.TryParseExact API docs · Updated June 2026
> quick_fix
Replace int.Parse(s) with int.TryParse(s, out int result). TryParse returns false on failure without throwing, letting you handle invalid input gracefully.
// BROKEN: throws FormatException on invalid input
int count = int.Parse(userInput);
// FIXED: TryParse — no exception on failure
if (int.TryParse(userInput, out int count))
{
// use count safely
}
else
{
// handle invalid input
return BadRequest("count must be a valid integer");
}
// DateTime parsing with culture
if (DateTime.TryParse(dateString,
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime date))
{
// use date
}What causes this error
FormatException is thrown by Parse methods (int.Parse, double.Parse, DateTime.Parse, Guid.Parse, etc.) when the input string does not match the expected format. Common triggers include empty strings, strings with letters when a number is expected, wrong date formats, and incorrect GUID or UUID strings.
How to fix it
- 01
step 1
Switch from Parse to TryParse
Every Parse method has a TryParse counterpart. TryParse(string, out T result) returns a bool — true on success, false on failure — and sets result to default(T) on failure. It never throws. Use TryParse whenever the input comes from outside your code.
- 02
step 2
Specify the culture for numeric and date parsing
int.Parse("1,000") works with en-US culture but fails with InvariantCulture. DateTime.Parse("06/10/2026") is ambiguous across cultures (MM/dd/yyyy vs dd/MM/yyyy). Always pass an explicit CultureInfo: `int.Parse(s, CultureInfo.InvariantCulture)` or `DateTime.Parse(s, new CultureInfo("en-GB"))`.
- 03
step 3
Validate the string before parsing
Null and empty strings always cause FormatException in Parse methods. Guard: `if (string.IsNullOrWhiteSpace(s)) return defaultValue;` before attempting any parse.
- 04
step 4
Use Convert class for flexible type conversion
Convert.ToInt32(s) throws FormatException for non-numeric strings like Parse, but Convert.ToInt32(null) returns 0 instead of throwing. Useful when null is acceptable but empty or non-numeric is not.
- 05
step 5
Provide meaningful error messages
When TryParse returns false, do not silently use the default. Log the invalid value and return a user-facing message: `$"'{userInput}' is not a valid integer for field 'count'."` This is especially important in web APIs.
How to verify the fix
- Test with valid input — parsing should succeed
- Test with empty string, null, and a string with letters — TryParse should return false without throwing
- Test with culture-specific formats if the application is international
Why FormatException happens at the runtime level
C#'s Parse methods are strict text parsers that enforce the exact lexical format for each type. They call into the underlying NumberStyles or DateTimeStyles parsing engine, which throws FormatException at the first character that does not conform to the expected pattern. The design is intentional: Parse is for trusted, well-formatted data, while TryParse is for external input. Using Parse on user-supplied or externally-sourced strings is the root cause of virtually every FormatException in production .NET applications.
Common debug mistakes for FormatException
- Using int.Parse() on query string parameters or form fields without null/whitespace checks
- Parsing DateTime without specifying a culture, causing environment-dependent failures
- Using Parse in unit tests with hardcoded valid strings but deploying code that handles user input — the tests never exercise the failure path
- Calling Guid.Parse(s) on a string that might be empty or a human-readable identifier rather than a GUID
When FormatException signals a deeper problem
FormatException is a symptom of treating external data as trusted. Every boundary where data enters your application — HTTP request parameters, file reads, database columns typed as string, deserialized JSON — is a potential source of misformatted values. The architectural pattern is to isolate parsing and validation at the boundary layer (controller, repository, mapper) and only allow strongly-typed values into the domain. A mediator or binding framework like ASP.NET Core model binding handles most of this automatically, but custom parsing code bypassing model binding is where FormatException lives.
Editor's take
FormatException in C# fires when you try to parse a string into a numeric or date type and the string doesn't match the expected format. It's deceptively simple — until you deploy to a server in a different locale. The classic production incident: `DateTime.Parse("06/16/2026")` works on your US-locale dev machine but throws FormatException on a European server where the day comes first. This is why experienced .NET developers always use `TryParse` with `CultureInfo.InvariantCulture` for any string-to-type conversion that touches user input or external data. The exception also appears frequently in CSV and API integrations where a field you expected to be numeric contains a currency symbol, thousands separator, or trailing whitespace. In high-throughput services, the performance cost of catching FormatException in a loop is significant — `TryParse` avoids the exception overhead entirely by returning a boolean. If you're building APIs, validate input formats at the controller level with model binding and data annotations rather than catching FormatException deep in your business logic. The pattern of 'parse and catch' versus 'validate then parse' is a fundamental C# design decision that separates brittle code from production-grade code. Knowing when FormatException fires means you understand .NET's type conversion pipeline.
By Bikram Nath · Curator · Updated June 2026
Frequently asked questions
What is the difference between FormatException and OverflowException in parsing?
FormatException means the string could not be parsed as the target type at all (e.g., 'abc' as int). OverflowException means the string was a valid number but too large for the target type (e.g., '99999999999' parsed as int overflows Int32.MaxValue). TryParse handles both and returns false for either failure.
Why does DateTime.Parse fail in some environments but not others?
DateTime.Parse uses the current thread's culture (Thread.CurrentThread.CurrentCulture) by default. On a US developer machine, 'MM/dd/yyyy' parses correctly; on a server with culture set to en-GB or a European locale, the same string fails. Always pass CultureInfo.InvariantCulture or the expected culture explicitly to DateTime.Parse or TryParseExact.
Is it better to use TryParse or a try-catch around Parse?
Always prefer TryParse. Try-catch around Parse is technically equivalent but significantly slower — exception creation in .NET has overhead. TryParse is designed exactly for the 'may or may not be valid' scenario and is the idiomatic .NET approach.