MadsLorentzen/ai-job-search · error · ValueError

ambiguous dot separator

Error message

ambiguous dot separator

What it means

Raised when a string contains exactly one dot in the pattern digits.3-digits (e.g. '1.234'). This is ambiguous between a US decimal ('1.234' = 1.234) and a European thousands separator ('1.234' = 1234), so the function refuses to guess and raises rather than risking a 1000x misinterpretation.

Source

Thrown at tools/convert_salary_excel.py:81

    text = value.strip().replace("\u00a0", " ").replace(" ", "")
    if not text:
        raise ValueError("not numeric")
    if "," in text and "." in text:
        # The separator that appears last is the decimal separator: European
        # "1.234,56" and US "1,234.56" are both unambiguous here, unlike the
        # single-separator cases below.
        if text.rfind(",") > text.rfind("."):
            text = text.replace(".", "").replace(",", ".")
        else:
            text = text.replace(",", "")
    elif "," in text:
        if re.fullmatch(r"[+-]?\d+,\d{3}", text):
            raise ValueError("ambiguous comma separator")
        text = text.replace(",", ".")
    elif "." in text:
        if re.fullmatch(r"[+-]?\d+\.\d{3}", text):
            raise ValueError("ambiguous dot separator")
    return float(text)


def header_matches(header, patterns):
    """Return True when a header contains a meaningful pattern match.

    Patterns match whole tokens; any pattern also listed in
    ``COMPOUND_PATTERNS`` may additionally match as a substring, to handle
    languages that form compound words.
    """
    h = header.lower().strip()
    tokens = set(re.findall(r"[a-zæøåöäü0-9]+", h))

    for p in patterns:
        if p in tokens:
            return True
        if p in COMPOUND_PATTERNS and p in h:
            return True

View on GitHub (pinned to 79cd383e58)

Solutions

  1. Apply the correct locale transform first: European sheets -> remove the dot ('1.234' -> '1234'); US sheets with 3-decimal fractions -> keep as-is after confirming intent
  2. Normalize the source column to include a decimal comma/dot that disambiguates (e.g. '1.234,5' or '1,234.5')
  3. Catch the ValueError, log the raw cell and row, and resolve via a locale flag or manual review

Example fix

// before
num = parse_numeric_cell('55.000')  # raises: 55000 or 55.0?

 after
num = parse_numeric_cell('55.000'.replace('.', ''))  # European sheet: 55000.0
Defensive patterns

Strategy: try-catch

Validate before calling

import re
AMBIG = re.compile(r'[+-]?\d+\.\d{3}$')
if isinstance(v, str) and AMBIG.fullmatch(v.strip()):
    v = v.replace('.', '' if locale == 'eu' else '.')  # eu: thousands sep

Type guard

def is_ambiguous_dot(v) -> bool:
    return isinstance(v, str) and bool(re.fullmatch(r'[+-]?\d+\.\d{3}', v.strip()))

Try / catch

try:
    num = parse_numeric_cell(v)
except ValueError as e:
    if 'ambiguous dot' in str(e):
        raise LocaleNeeded(v)
    raise

Prevention

When it happens

Trigger: Passing a string that fullmatches r'[+-]?\d+\.\d{3}' such as '1.234', '65.500', or '2.000'. Typical for European-formatted salaries ('2.000' meaning two thousand) or US decimals with exactly three fraction digits ('1.234').

Common situations: Danish/European Excel exports where '.' is the thousands separator ('55.000' kr), or US sheets with values like '0.125'. Without a second separator or locale hint the format cannot be inferred from the string alone.

Related errors


AI-assisted analysis of MadsLorentzen/ai-job-search@79cd383e58 (2026-08-27). Data as JSON: /api/errors/3d7907b79ca6c64f. Report an issue: GitHub.