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
- Set hparams.tts_cleaner_names to one of the names actually defined in synthesizer/utils/cleaners.py: 'english_cleaners', 'transliteration_cleaners', or 'basic_cleaners'.
- If you need a custom cleaner, define it as a module-level function in synthesizer/utils/cleaners.py and reference that exact name.
- 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
- Validate tts_cleaner_names against the cleaners module at config load time, not at first text encoding.
- After editing hparams or cleaners.py, smoke-test one text_to_sequence() call before starting preprocessing/training.
- Keep cleaner names in one constant list shared by training and inference so the two cannot drift apart.
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
- `hparams.synthesis_batch_size` must be evenly divisible by n
- `batch_size` must be evenly divisible by n_gpus!
- No synthesizer models found in %s
- Unknown model mode value -
AI-assisted analysis of CorentinJ/Real-Time-Voice-Cloning@890f3a0318 (2026-08-15).
Data as JSON: /api/errors/d5faddb87ed1c3fd.
Report an issue: GitHub.