ValueError: could not convert string to float
Exception: ValueErrorCategory: runtime (conversion)Raised at: the float() call that received text it cannot parse as a number
What this error means
float() parses text into a number, and it accepts a surprisingly narrow set of forms: digits, an optional sign, one decimal point, optional exponent notation, and the special literals inf, -inf and nan. Anything else raises ValueError.
The message quotes the exact string that failed, which makes this one of the more informative Python errors. Read the quoted part carefully — it usually shows the offending character right there.
Traceback (most recent call last):
File "demo.py", line 2, in <module>
price = float("$1,299.00")
ValueError: could not convert string to float: '$1,299.00'
The seven inputs that break float()
float("$1,299.00") # 💥 currency symbol and thousands comma
float("1,299.00") # 💥 comma is not a thousands separator to float()
float("1.299,00") # 💥 European decimal comma
float(" ") # 💥 empty or whitespace-only
float("") # 💥 empty
float("12 kg") # 💥 trailing unit
float("12%") # 💥 percent sign
float("--") # 💥 placeholder text from a spreadsheet
float("nan") # ✅ parses to nan
float("1e-3") # ✅ 0.001
float(" 42.5 ") # ✅ surrounding whitespace IS allowed
float("+3.5") # ✅ sign is allowed
Note the last two: whitespace around the number is fine, and a leading sign is fine. It is punctuation *inside* or attached to the digits that fails. That is why strip() alone so often looks like it should work and does not.
Where these values come from
Almost every real case involves data written by a human or a spreadsheet rather than by a program. Three sources dominate:
- Spreadsheets and CSV exports. Currency formatting, thousands separators, and empty cells that arrive as
"". A blank cell in a numeric column is the single most common cause in practice. - User input.
input()always returns a string, and people type1,5or12kgor press Enter with nothing. - Locale differences. A European export writes
1.299,00where an American one writes1,299.00— the same number, opposite punctuation.
A cleaning pipeline that handles all of them
def parse_float(raw, default=None):
'''Parse a messy numeric string, returning default when it cannot be read.'''
if raw is None:
return default
s = str(raw).strip()
if not s or s in {"-", "--", "N/A", "NA", "n/a", "."}:
return default
s = s.replace("$", "").replace("€", "").replace("£", "").replace("₹", "")
s = s.replace(",", "") # thousands separator
s = s.replace("%", "")
# split off a trailing unit: '12 kg' -> '12'
s = s.split()[0] if s.split() else s
try:
return float(s)
except ValueError:
return default
parse_float("$1,299.00") # 1299.0
parse_float("12 kg") # 12.0
parse_float("--") # None
parse_float("") # None
Two cautions about that function. Removing commas blindly will corrupt European-style 1.299,00, so if your data uses decimal commas, convert those first with s.replace('.', '').replace(',', '.'). And returning default silently hides bad rows — log what you skipped so you can see how much of your data is unusable.
Reading a CSV safely
import csv
rows = []
with open("sales.csv", newline="") as f:
for n, row in enumerate(csv.DictReader(f), start=2): # header is line 1
try:
row["total"] = float(row["total"])
except ValueError:
print(f"line {n}: cannot parse {row['total']!r}")
row["total"] = 0.0
rows.append(row)
Tracking the line number matters. A CSV with one bad row out of ten thousand will otherwise fail on row 9,847 and tell you nothing about where to look. Including the row number in the message turns a crash into a five-second fix.
float() versus int()
A closely related trap: int() is stricter than float(). It refuses a decimal string outright:
float("3.5") # ✅ 3.5
int("3.5") # 💥 ValueError: invalid literal for int() with base 10
int(float("3.5")) # ✅ 3 — converts through float first
int(3.9) # ✅ 3 — an actual float truncates toward zero
int(" 7 ") # ✅ whitespace is fine for int() too
So when reading decimal text into an integer, go through float() first and then decide whether to truncate or round. int(float(x)) truncates; round(float(x)) rounds to nearest.
Related messages worth knowing
- ValueError: invalid literal for int() with base 10 — the integer-shaped twin of this exact message.
- ValueError: the parent guide — the whole family of right-type-wrong-value failures.
- UnicodeDecodeError — what you hit when the file encoding is wrong before parsing even starts.
🇮🇳 Hindi में समझें
ValueError: could not convert string to float tab aata hai jab float() ko aisa text mile jise wo number me na badal sake. float() kaafi narrow set accept karta hai: digits, optional sign, ek decimal point, exponent notation (1e-3), aur inf/nan. Baaki sab fail. Ye message us exact string ko quote karta hai jo fail hui — isliye quoted hisse ko dhyan se padho, offending character wahin dikhta hai. Saat common wajah: currency symbol ($1299), thousands comma (1,299.00 — float comma ko separator nahi maanta), European decimal comma (1.299,00), khaali ya sirf-space string, unit ke saath (12 kg), percent sign (12%), aur spreadsheet ka placeholder (--). Do cheezein yaad rakho: number ke aas-paas ka whitespace theek hai, aur leading sign theek hai — problem digits ke andar ya unse chipki hui punctuation hai. Isi wajah se sirf strip() aksar kaam nahi karta. Zyada tar real cases spreadsheet, CSV export ya user input se aate hain — blank numeric cell sabse common wajah hai. Fix: ek cleaning function likho jo symbols hataye, comma hataaye, trailing unit split kare, aur try/except ValueError me default de. CSV padhte waqt line number bhi print karo, warna 10,000 rows me se ek kharab row par crash hoga aur pata nahi chalega kahaan. Aur int() float() se zyada strict hai — int('3.5') fail hota hai, int(float('3.5')) karo.