jamiepine/voicebox · error · ValueError

No samples found for profile {profile_id}

Error message

No samples found for profile {profile_id}

What it means

Raised in the cloned branch of create_voice_prompt_from_profile() when db.query(DBProfileSample).filter_by(profile_id=profile_id).all() returns an empty list. Cloned profiles are built from uploaded audio samples; with zero samples there is no source audio to clone from, so the function aborts before invoking the TTS backend.

Source

Thrown at backend/services/profiles.py:577

        }

    # ── Designed profiles: return text description (future) ──
    if voice_type == "designed":
        if not profile.design_prompt or not profile.design_prompt.strip():
            raise ValueError(f"Designed profile {profile_id} is missing design_prompt")
        return {
            "voice_type": "designed",
            "design_prompt": profile.design_prompt,
        }

    if engine not in CLONING_ENGINES:
        raise ValueError(f"Engine '{engine}' does not support cloned voice profiles")

    # ── Cloned profiles: create from audio samples ──
    samples = db.query(DBProfileSample).filter_by(profile_id=profile_id).all()

    if not samples:
        raise ValueError(f"No samples found for profile {profile_id}")

    tts_model = get_tts_backend_for_engine(engine)

    if len(samples) == 1:
        sample = samples[0]
        sample_audio_path = config.resolve_storage_path(sample.audio_path)
        if sample_audio_path is None:
            raise ValueError(f"Sample audio not found for profile {profile_id}")
        voice_prompt, _ = await tts_model.create_voice_prompt(
            str(sample_audio_path),
            sample.reference_text,
            use_cache=use_cache,
        )
        return voice_prompt

    audio_paths = []
    for sample in samples:
        sample_audio_path = config.resolve_storage_path(sample.audio_path)

View on GitHub (pinned to 51f49dea19)

Solutions

  1. Upload at least one audio sample to the profile before requesting voice prompt creation.
  2. Check the sample upload endpoint returned success and that DBProfileSample rows exist for the profile_id.
  3. In the API layer, guard with: if not db.query(DBProfileSample).filter_by(profile_id=pid).count(): return 400 'No samples uploaded'.
  4. If samples were lost, re-upload them; if the profile is unused, delete it.

Example fix

// before
prompt = await create_voice_prompt_from_profile(profile_id, db, engine='qwen')  // profile has no samples
// after: ensure a sample exists first
count = db.query(DBProfileSample).filter_by(profile_id=profile_id).count()
if count == 0:
    raise HTTPException(400, "Upload at least one audio sample first")
prompt = await create_voice_prompt_from_profile(profile_id, db, engine='qwen')
Defensive patterns

Strategy: validation

Validate before calling

from backend.models import DBProfileSample

def has_samples(db, profile_id) -> bool:
    return db.query(DBProfileSample).filter_by(profile_id=profile_id).count() > 0

if (profile.voice_type or 'cloned') == 'cloned' and not has_samples(db, profile_id):
    raise HTTPException(400, 'Upload at least one audio sample before synthesis')

Try / catch

try:
    prompt = await create_voice_prompt_from_profile(profile_id, db, engine=engine)
except ValueError as e:
    if 'No samples found' in str(e):
        raise HTTPException(400, str(e))
    raise

Prevention

When it happens

Trigger: Creating a profile with voice_type='cloned' but never uploading samples via the sample upload endpoint; samples were deleted; profile_id belongs to a freshly created profile before any sample upload completed.

Common situations: User creates a profile in the UI but abandons before uploading audio; sample upload failed silently so the profile row exists without sample rows; cleanup script removed samples but not profiles; test creates a profile fixture without seeding samples.

Related errors


AI-assisted analysis of jamiepine/voicebox@51f49dea19 (2026-08-12). Data as JSON: /api/errors/27836fb4e792bef9. Report an issue: GitHub.