fishaudio/fish-speech · error · FileExistsError
Reference ID '{id}' already exists
Error message
Reference ID '{id}' already exists What it means
add_reference stores each voice reference under references/<id>/. If that directory already exists, the ID is taken and a FileExistsError is raised before any file is written, preventing silent overwrites of existing references.
Source
Thrown at fish_speech/inference_engine/reference_loader.py:209
"""
Add a new reference voice by creating a new directory and copying files.
Args:
id: Reference ID (directory name)
wav_file_path: Path to the audio file to copy
reference_text: Text content for the .lab file
Raises:
FileExistsError: If the reference ID already exists
FileNotFoundError: If the audio file doesn't exist
OSError: If file operations fail
"""
self._validate_id(id)
# Check if reference already exists
ref_dir = Path("references") / id
if ref_dir.exists():
raise FileExistsError(f"Reference ID '{id}' already exists")
# Check if audio file exists
audio_path = Path(wav_file_path)
if not audio_path.exists():
raise FileNotFoundError(f"Audio file not found: {wav_file_path}")
# Validate audio file extension
if audio_path.suffix.lower() not in AUDIO_EXTENSIONS:
raise ValueError(
f"Unsupported audio format: {audio_path.suffix}. Supported formats: {', '.join(AUDIO_EXTENSIONS)}"
)
try:
# Create reference directory
ref_dir.mkdir(parents=True, exist_ok=False)
# Determine the target audio filename with original extension
target_audio_path = ref_dir / f"sample{audio_path.suffix}"View on GitHub (pinned to befe400174)
Solutions
- Use delete_reference(id) first, then add_reference again
- Choose a unique ID (append a suffix/version, e.g. "speaker_v2")
- Wrap add_reference in try/except FileExistsError for idempotent ingestion scripts
Example fix
# before
loader.add_reference("my_voice", "a.wav") # FileExistsError on second run
# after
try:
loader.add_reference("my_voice", "a.wav")
except FileExistsError:
loader.delete_reference("my_voice")
loader.add_reference("my_voice", "a.wav") Defensive patterns
Strategy: try-catch
Validate before calling
from pathlib import Path
if (Path("references") / ref_id).exists():
print(f"reference '{ref_id}' already registered; skipping or replacing") Try / catch
try:
loader.add_reference(ref_id, wav)
except FileExistsError:
loader.delete_reference(ref_id)
loader.add_reference(ref_id, wav) Prevention
- Make ingestion scripts idempotent: check-then-add or catch FileExistsError
- Version reference IDs instead of reusing names
When it happens
Trigger: Calling add_reference(id=...) twice with the same ID (even if the wav differs), or re-running a script that registers references after a previous partial/complete run.
Common situations: Re-running ingestion scripts without cleanup, retrying after a failure that had already created the directory (mkdir with exist_ok=False happens later, but this check fires first).
Related errors
- Either text or tokens must be provided
- Unsupported part type: {part['type']}
- Unsupported part type: {type(part)}
- {i} is not a file or directory
- Expected GenerateResponse, got {type(wrapped_result.response
AI-assisted analysis of fishaudio/fish-speech@befe400174 (2026-08-27).
Data as JSON: /api/errors/2fbcbdd475caf018.
Report an issue: GitHub.