Skip to main content

How to Resolve Python Error "ValueError: invalid literal for int() with base 10"

The ValueError: invalid literal for int() with base 10: '...' is a frequent Python error encountered when using the int() function to convert a string to an integer. It signifies that the string provided to int() does not represent a valid whole number in base 10 (our standard decimal system) and therefore cannot be directly converted.

This guide explains the common reasons for this error – like non-digit characters, decimal points, or empty strings – and provides solutions for handling or cleaning the input string before conversion.

Understanding the Error: What int() Expects

The built-in int() function, when given a string argument, attempts to parse that string as an integer according to the specified base (which defaults to base 10). For base 10, a valid string must:

  • Contain only digit characters (0 through 9).
  • Optionally have a leading sign (+ or -).
  • Not contain decimal points (.) or other non-digit characters (letters, symbols, spaces within the number).
  • Not be empty or contain only whitespace after stripping.

The ValueError occurs when the input string violates these rules. The part of the error message after the colon (: '...') shows the specific invalid literal (the string) that int() could not parse.

Cause 1: String Contains Non-Digit Characters

This includes letters, symbols, spaces within the digits, or other characters that aren't 0-9 (or a leading sign).

Error Scenario

string_with_letters = "12a3"
string_with_symbols = "1,000" # Comma is not a digit
string_with_spaces = "1 2 3"

try:
# ⛔️ ValueError: invalid literal for int() with base 10: '12a3'
num = int(string_with_letters)
except ValueError as e:
print(e)

try:
# ⛔️ ValueError: invalid literal for int() with base 10: '1,000'
num = int(string_with_symbols)
except ValueError as e:
print(e)

try:
# ⛔️ ValueError: invalid literal for int() with base 10: '1 2 3'
num = int(string_with_spaces)
except ValueError as e:
print(e)

Solution: Validate Input / Handle Errors (try...except)

Especially when dealing with user input or external data, you cannot guarantee the string will be valid. The most robust approach is to wrap the int() call in a try...except ValueError block.

user_input = input("Enter a whole number: ") # User might enter 'abc'

try:
# Attempt conversion
number = int(user_input)
print(f"You entered the integer: {number}")
except ValueError:
# Handle the case where conversion fails
print(f"Invalid input: '{user_input}' is not a valid whole number.")
# Optionally, assign a default value, re-prompt, or raise a custom error
number = 0 # Example fallback
note

This prevents the program from crashing and allows you to handle invalid input gracefully.

Solution: Extract Digits Before Conversion (If Appropriate)

If you know the string might contain non-digits but you only want to convert the digits present, you can filter them out first. Use this cautiously, as it might not be appropriate for all inputs (e.g., "1a2b" becomes 12).

import re

mixed_string = "ID: 456-ABC"

# Using filter (keeps only digits)
digits_only = "".join(filter(str.isdigit, mixed_string))
print(f"Digits extracted: '{digits_only}'") # Output: '456'
if digits_only: # Check if any digits were found
number = int(digits_only)
print(f"Converted number: {number}") # Output: 456
else:
print("No digits found in string.")

# Using regular expressions (more flexible)
match = re.search(r'\d+', mixed_string) # Find first sequence of digits
if match:
number_re = int(match.group(0))
print(f"First number found (regex): {number_re}") # Output: 456
else:
print("No number sequence found.")
note

Filtering or regex extraction should only be used when that specific logic matches your requirements.

Cause 2: String Represents a Float (Contains Decimal Point)

The int() function cannot directly parse strings containing a decimal point (.), even if the fractional part is zero (like "5.0").

Error Scenario

float_string = "123.45"
zero_decimal_string = "5.0"

try:
# ⛔️ ValueError: invalid literal for int() with base 10: '123.45'
num = int(float_string)
except ValueError as e:
print(e)

try:
# ⛔️ ValueError: invalid literal for int() with base 10: '5.0'
num = int(zero_decimal_string)
except ValueError as e:
print(e)

Solution: Convert to float() First, then int()

The standard way to handle this is to first convert the string to a float using float(), and then convert that float to an int. Converting a float to an int truncates (removes) the decimal part.

float_string = "123.45"
zero_decimal_string = "5.0"

try:
# ✅ Convert string -> float -> int
num_float = float(float_string) # Converts to 123.45
num_int = int(num_float) # Truncates to 123
print(f"'{float_string}' -> float: {num_float} -> int: {num_int}")
# Output: '123.45' -> float: 123.45 -> int: 123

num_float_zero = float(zero_decimal_string) # Converts to 5.0
num_int_zero = int(num_float_zero) # Truncates to 5
print(f"'{zero_decimal_string}' -> float: {num_float_zero} -> int: {num_int_zero}")
# Output: '5.0' -> float: 5.0 -> int: 5

except ValueError:
print("String is not a valid float.")

Handling Rounding (Optional)

If you need standard rounding instead of truncation when converting from a float string:

import math

float_string = "123.78"
float_string_low = "123.12"

# ✅ Convert string -> float -> round -> int
num_int_rounded = int(round(float(float_string)))
print(f"'{float_string}' rounded to int: {num_int_rounded}") # Output: 124

# Round up: string -> float -> math.ceil -> int
num_int_ceil = int(math.ceil(float(float_string)))
print(f"'{float_string}' ceiling to int: {num_int_ceil}") # Output: 124

# Round down: string -> float -> math.floor -> int
num_int_floor = int(math.floor(float(float_string_low)))
print(f"'{float_string_low}' floor to int: {num_int_floor}") # Output: 123

Cause 3: Empty or Whitespace-Only String

Passing an empty string ("") or a string containing only whitespace (" ") to int() will also cause a ValueError.

Error Scenario

empty_str = ""
space_str = " "

try:
# ⛔️ ValueError: invalid literal for int() with base 10: ''
num = int(empty_str)
except ValueError as e:
print(e)

try:
# ⛔️ ValueError: invalid literal for int() with base 10: ' '
num = int(space_str)
except ValueError as e:
print(e)

Solution: Check and Provide Default (e.g., or '0')

Use string stripping and the or operator to provide a default value (like '0') if the string is empty after stripping whitespace.

empty_str = ""
space_str = " "

# ✅ Use .strip() and 'or' to provide '0' for empty/whitespace strings
num_empty = int(empty_str.strip() or '0')
print(f"Result for empty string: {num_empty}") # Output: Result for empty string: 0

num_space = int(space_str.strip() or '0')
print(f"Result for space string: {num_space}") # Output: Result for space string: 0

valid_str = " 123 "
num_valid = int(valid_str.strip() or '0')
print(f"Result for valid string: {num_valid}") # Output: Result for valid string: 123
  • my_str.strip(): Removes leading/trailing whitespace.
  • ... or '0': If my_str.strip() results in an empty string (which is falsy), the expression evaluates to '0'. Otherwise, it evaluates to the stripped string.

Solution: Use if Check Before Conversion

Explicitly check if the stripped string is non-empty.

maybe_empty = "  "
number = 0 # Default

stripped = maybe_empty.strip()
if stripped: # Check if string is non-empty after stripping
try:
number = int(stripped)
print("Conversion successful.")
except ValueError:
print(f"Stripped string '{stripped}' is not a valid integer.")
else:
print("String is empty or contains only whitespace.") # This is executed

print(f"Final number: {number}")

Best Practice: Use try...except ValueError

Because you often cannot guarantee the format of strings coming from external sources (user input, files, APIs), the most robust and Pythonic way to handle potential conversion errors is to always wrap int() calls in a try...except ValueError block when dealing with strings.

def safe_string_to_int(input_str, default=0):
"""Safely converts a string to an int, returning default on failure."""
try:
# Attempt conversion after stripping whitespace
return int(input_str.strip())
except (ValueError, TypeError, AttributeError): # Catch errors if input is None, not string, or invalid format
print(f"Warning: Could not convert '{input_str}' to int. Returning default.")
return default

# Example Usage
print(safe_string_to_int(" 123 ")) # Output: 123
print(safe_string_to_int("45a")) # Output: Warning... Returning default. -> 0
print(safe_string_to_int(" ")) # Output: Warning... Returning default. -> 0
print(safe_string_to_int(None)) # Output: Warning... Returning default. -> 0
print(safe_string_to_int("5.6")) # Output: Warning... Returning default. -> 0

Output:

123
Warning: Could not convert '45a' to int. Returning default.
0
Warning: Could not convert ' ' to int. Returning default.
0
Warning: Could not convert 'None' to int. Returning default.
0
Warning: Could not convert '5.6' to int. Returning default.
0

Conclusion

The ValueError: invalid literal for int() with base 10 occurs when you pass a string to int() that doesn't strictly represent a whole number in base 10.

Key solutions include:

  1. Handle Invalid Characters: Use try...except ValueError to catch errors from strings containing non-digits (letters, symbols, internal spaces). Optionally pre-process strings to remove/extract digits if appropriate.
  2. Handle Float Strings: Convert float-like strings (e.g., "123.45") to float() first, then to int() (which truncates). Use round(), math.ceil(), or math.floor() after float() if specific rounding is needed.
  3. Handle Empty/Whitespace Strings: Use .strip() combined with the or '0' fallback or an if check before calling int().

Using try...except ValueError is the most reliable way to handle potentially invalid string inputs before integer conversion.