CorentinJ/Real-Time-Voice-Cloning · error · Exception

Unknown cleaner: %s

Error message

Unknown cleaner: %s

What it means

Raised by _clean_text() in synthesizer/utils/text.py when a name in cleaner_names does not resolve to a usable function on the cleaners module (synthesizer/utils/cleaners.py). Cleaners normalize raw text (lowercasing, number expansion, transliteration) before symbol encoding; the valid names defined in this repo are 'english_cleaners', 'transliteration_cleaners', and 'basic_cleaners'. Caveat: the check uses getattr(cleaners, name) without a default, so a truly misspelled name actually raises AttributeError first; this explicit Exception fires when the attribute exists but is falsy (e.g. a None imported into the cleaners namespace).

Source

Thrown at synthesizer/utils/text.py:61

def sequence_to_text(sequence):
    """Converts a sequence of IDs back to a string"""
    result = ""
    for symbol_id in sequence:
        if symbol_id in _id_to_symbol:
            s = _id_to_symbol[symbol_id]
            # Enclose ARPAbet back in curly braces:
            if len(s) > 1 and s[0] == "@":
                s = "{%s}" % s[1:]
            result += s
    return result.replace("}{", " ")


def _clean_text(text, cleaner_names):
    for name in cleaner_names:
        cleaner = getattr(cleaners, name)
        if not cleaner:
            raise Exception("Unknown cleaner: %s" % name)
        text = cleaner(text)
    return text


def _symbols_to_sequence(symbols):
    return [_symbol_to_id[s] for s in symbols if _should_keep_symbol(s)]


def _arpabet_to_sequence(text):
    return _symbols_to_sequence(["@" + s for s in text.split()])


def _should_keep_symbol(s):
    return s in _symbol_to_id and s not in ("_", "~")

View on GitHub (pinned to 890f3a0318)

Solutions

  1. Set hparams.tts_cleaner_names to one of the names actually defined in synthesizer/utils/cleaners.py: 'english_cleaners', 'transliteration_cleaners', or 'basic_cleaners'.
  2. If you need a custom cleaner, define it as a module-level function in synthesizer/utils/cleaners.py and reference that exact name.
  3. If you intended a cleaner from another project (e.g. 'english_cleaners2' from NVIDIA Tacotron2), port its implementation into cleaners.py first.

Example fix

# before
hparams.tts_cleaner_names = ["english_cleaners2"]  # not defined in this repo's cleaners.py

# after
hparams.tts_cleaner_names = ["english_cleaners"]  # defined in synthesizer/utils/cleaners.py
Defensive patterns

Strategy: validation

Validate before calling

from synthesizer.utils import cleaners

VALID_CLEANERS = {"english_cleaners", "transliteration_cleaners", "basic_cleaners"}

def validate_cleaners(names):
    bad = [n for n in names if not callable(getattr(cleaners, n, None))]
    if bad:
        raise ValueError(f"Unknown cleaners {bad}; valid: {sorted(VALID_CLEANERS)}")
    return names

Type guard

from synthesizer.utils import cleaners
import inspect

def is_valid_cleaner(name: str) -> bool:
    fn = getattr(cleaners, name, None)
    return inspect.isfunction(fn) and fn.__module__ == cleaners.__name__

Try / catch

try:
    seq = text_to_sequence(text, hparams.tts_cleaner_names)
except Exception as e:
    if "Unknown cleaner" in str(e) or isinstance(e, AttributeError):
        raise ValueError(f"Check hparams.tts_cleaner_names={hparams.tts_cleaner_names} against synthesizer/utils/cleaners.py") from e
    raise

Prevention

When it happens

Trigger: text_to_sequence(text, hparams.tts_cleaner_names) — called by synthesizer/inference.py:89 and synthesizer_dataset.py:39 — with tts_cleaner_names containing a name that is not one of the three defined cleaner functions, or a name shadowed by a None/variable in cleaners.py. The list comes from synthesizer/hparams.py (default ['english_cleaners']).

Common situations: Copying hparams from another Tacotron fork whose cleaner names differ (e.g. 'english_cleaners2', 'vietnamese_cleaners'); editing tts_cleaner_names to try a new cleaner before implementing it; a typo; porting a custom cleaners.py that defines the name as a variable rather than a function.

Related errors


AI-assisted analysis of CorentinJ/Real-Time-Voice-Cloning@890f3a0318 (2026-08-15). Data as JSON: /api/errors/d5faddb87ed1c3fd. Report an issue: GitHub.