High severity HTTP 401 intermediate · Fix: 5-10 min

HFValidationError

huggingface_hub.utils.HFValidationError

What this error means
WhisperX's diarization pipeline requires HuggingFace authentication to download pyannote.audio models, and fails with HFValidationError when the token is missing, invalid, or lacks required permissions.

Stack trace

traceback
huggingface_hub.utils.HFValidationError: Token is invalid. It must be a user access token (not a system token or API token) with 'read' permissions on model repositories.

Or:

huggingface_hub.utils._headers.HFUserAgentError: 401 Client Error: Unauthorized for url: https://huggingface.co/pyannote/speaker-diarization/resolve/main/pytorch_model.bin

Or:

FileNotFoundError: Model pyannote/speaker-diarization-3.0 not found. You need to accept the model license at https://huggingface.co/pyannote/speaker-diarization-3.0 before using it.

Traceback (most recent call last):
  File "<your_code>.py", line X, in <module>
    diarize_model = whisperx.DiarizationPipeline(model_name="pyannote/speaker-diarization-3.0")
  File "site-packages/whisperx/diarization.py", line 89, in __init__
    self.model = Pipeline.from_pretrained(model_name, use_auth_token=use_auth_token)
  File "site-packages/pyannote/audio/core/pipeline.py", line 198, in from_pretrained
    model = torch.hub.load(...)
  File "site-packages/huggingface_hub/hub_mixin.py", line 135, in from_pretrained
    raise HFValidationError(f"Token is invalid...")
QUICK FIX
Create a new HuggingFace 'User Access Token' at https://huggingface.co/settings/tokens with 'Read' permissions, accept the pyannote license at https://huggingface.co/pyannote/speaker-diarization-3.0, then pass it to WhisperX: `export HF_TOKEN='hf_xxxxx'` before running.

Why it happens

WhisperX's diarization pipeline downloads pre-trained pyannote.audio models from HuggingFace Hub at runtime. These models require explicit user authentication because they have license agreements (research-only, non-commercial). WhisperX passes the HuggingFace token to pyannote, which validates it against HuggingFace's servers. The error occurs when: (1) no token is provided, (2) the token is invalid or expired, (3) the token lacks 'read' permissions, (4) the token's associated user hasn't accepted the model license, or (5) the token is a legacy 'API token' instead of a 'user access token' (deprecated in 2024).

Detection

Before deploying WhisperX with diarization, test the authentication locally with: `from whisperx.diarization import DiarizationPipeline; DiarizationPipeline(model_name='pyannote/speaker-diarization-3.0')` to catch token issues before production. Add debug logging: `import logging; logging.basicConfig(level=logging.DEBUG)` to see the exact HTTP 401 response from HuggingFace.

Causes & fixes

1

HuggingFace token not set in environment or passed to WhisperX

✓ Fix

Set the HF_TOKEN environment variable: `export HF_TOKEN='hf_xxxxx'` before running, or pass it explicitly: `diarize_model = whisperx.DiarizationPipeline(model_name='pyannote/speaker-diarization-3.0', use_auth_token=os.environ['HF_TOKEN'])`

2

Using deprecated 'API token' instead of 'user access token' (HuggingFace deprecated API tokens in 2024)

✓ Fix

Go to https://huggingface.co/settings/tokens, delete the old 'API token', create a new 'User Access Token' with 'Read' permissions, and use that token value instead

3

HuggingFace token is valid but user account hasn't accepted the pyannote model license

✓ Fix

Visit https://huggingface.co/pyannote/speaker-diarization-3.0, log in with your HuggingFace account, accept the license agreement, then retry with your token

4

Token has insufficient permissions (missing 'read' scope or restricted to specific repos)

✓ Fix

Create a new HuggingFace User Access Token with 'Read' permissions (no repo restrictions) at https://huggingface.co/settings/tokens: do NOT restrict it to specific repositories

Code: broken vs fixed

Broken - triggers the error
python
#!/usr/bin/env python3
import whisperx
import os

# BROKEN: no HuggingFace token provided, or token not in environment
audio_path = 'sample.mp3'
device = 'cuda'
batch_size = 16

# Load base model
model = whisperx.load_model('base', device=device)

# Transcribe
result = model.transcribe(audio_path, batch_size=batch_size)

# FAILS HERE with HFValidationError — no token passed to diarization
diarize_model = whisperx.DiarizationPipeline(
    model_name='pyannote/speaker-diarization-3.0',
    use_auth_token=None  # ← BROKEN: None means no authentication
)

diarize_result = diarize_model(audio_path)
print(diarize_result)
Fixed - works correctly
python
#!/usr/bin/env python3
import whisperx
import os
from huggingface_hub import login

# FIXED: Load HuggingFace token from environment
hf_token = os.environ.get('HF_TOKEN')
if not hf_token:
    raise ValueError('HF_TOKEN environment variable not set. Create a token at https://huggingface.co/settings/tokens')

# Pre-authenticate with HuggingFace (ensures pyannote can download models)
login(token=hf_token, add_to_git_credential=False)

audio_path = 'sample.mp3'
device = 'cuda'
batch_size = 16

# Load base model
model = whisperx.load_model('base', device=device)

# Transcribe
result = model.transcribe(audio_path, batch_size=batch_size)

# FIXED: Pass token explicitly to diarization pipeline
diarize_model = whisperx.DiarizationPipeline(
    model_name='pyannote/speaker-diarization-3.0',
    use_auth_token=hf_token  # ← FIXED: Token from environment
)

diarize_result = diarize_model(audio_path)
print('Diarization succeeded:', diarize_result)
Added login() from huggingface_hub to pre-authenticate before creating the diarization pipeline, and passed the HF_TOKEN environment variable explicitly to use_auth_token instead of None, ensuring pyannote can access and download the licensed model.

Workaround

If you cannot obtain a valid HuggingFace token immediately, skip speaker diarization in WhisperX and use an open-source diarization alternative that doesn't require authentication: (1) Use `pyannote-speaker-diarization` with the open-source 'speechbrain/spkrec-ecapa-voxceleb' model instead, or (2) transcribe with WhisperX's base model only, then use Silero Speaker Diarization (open-source, no token needed) as a separate step, or (3) temporarily disable diarization: `result = model.transcribe(audio_path, batch_size=batch_size); # skip diarization step` and add speaker labels manually via clustering.

Prevention

Use HuggingFace token management best practices: (1) Store tokens in `.env` files or secret managers (never hardcode), (2) use `huggingface_hub.login()` at application startup to validate the token early, (3) set token expiration reminders (HF tokens are permanent but policies change), (4) monitor HFValidationError exceptions at API boundaries and log token validation failures for alerting, (5) for production services, use HuggingFace 'fine-grained tokens' with minimal necessary scopes rather than full read-access tokens.

Python 3.9+ · whisperx >=3.0.0 · tested on 3.1.x with pyannote.audio>=2.1.0 and huggingface-hub>=0.17.0
Verified 2026-04 · pyannote/speaker-diarization-3.0, openai/whisper
Verify ↗

Community Notes

No notes yetBe the first to share a version-specific fix or tip.