Configured QuerySplittingBehavior.SplitQuery in PostgresDatabaseProvider to optimize performance for queries with multiple Include() statements. This prevents cartesian explosion, eliminates EF Core warnings, and aligns with best practices for handling related collections in PostgreSQL.
11 KiB
WebSocket "Token is required" Error - Not a Bug!
Error Message: Token is required. URL GET /socket
Location: Jellyfin.Api.Middleware.ExceptionMiddleware
Status: ✅ Expected Behavior (Not a Bug)
What This Error Means
The Message
[WRN] Jellyfin.Api.Middleware.ExceptionMiddleware: Error processing request:
Token is required. URL GET /socket
What's Happening
- A client (web browser, mobile app, etc.) is trying to connect to the WebSocket endpoint
- The WebSocket endpoint
/socketrequires authentication - The client didn't provide a valid authentication token
- Jellyfin correctly rejects the connection
This is SECURITY WORKING AS INTENDED ✅
Why WebSockets Require Authentication
Code Location
File: Emby.Server.Implementations/HttpServer/WebSocketManager.cs
Method: WebSocketRequestHandler()
public async Task WebSocketRequestHandler(HttpContext context)
{
// Authenticate the request
var authorizationInfo = await _authService.Authenticate(context.Request).ConfigureAwait(false);
// Reject if not authenticated
if (!authorizationInfo.IsAuthenticated)
{
throw new SecurityException("Token is required");
}
// Continue with WebSocket connection...
}
Why Authentication Is Required
-
Real-Time Updates - WebSockets send real-time events about:
- Library changes
- Playback status
- User activities
- System notifications
-
Personal Data - WebSocket messages contain:
- User-specific information
- Viewing history
- Preferences
- Session data
-
Security - Without authentication:
- Anyone could listen to events
- Privacy violation
- Potential data leak
Common Causes
1. Browser Extension or Developer Tools ⚠️
Scenario: Browser trying to auto-connect WebSocket
// Browser dev tools or extension
var ws = new WebSocket('ws://localhost:8096/socket');
// ❌ No token provided → "Token is required" error
Solution: Ignore - this is external tools testing
2. Web Client Not Sending Token
Scenario: Jellyfin web client not properly authenticated
Possible causes:
- Session expired
- Cookie cleared
- Fresh installation without login
Solution: Log in to web UI at http://localhost:8096
3. Third-Party Client Issues
Scenario: Mobile app or third-party client with authentication issues
Solution:
- Re-authenticate in the client
- Check client API token configuration
- Update client to latest version
4. Development/Testing Scripts
Scenario: Testing WebSocket without authentication
Solution: Add proper authentication:
// Correct WebSocket connection with token
const accessToken = 'your-jellyfin-api-token';
const ws = new WebSocket(`ws://localhost:8096/socket?api_key=${accessToken}`);
How to Fix (If Needed)
Option 1: Ignore the Error (Recommended) ✅
When: Error appears occasionally and doesn't affect functionality
Action: Nothing - this is normal
Reason:
- Browsers test WebSocket connections
- Extensions probe endpoints
- Development tools auto-connect
- These are expected failed attempts
In startup.json or appsettings.json:
{
"Serilog": {
"MinimumLevel": {
"Override": {
"Jellyfin.Api.Middleware.ExceptionMiddleware": "Error"
}
}
}
}
This reduces warning noise while keeping actual errors visible.
Option 2: Check Web Client Authentication
When: Error happens every time you load web UI
Steps:
-
Clear browser cache and cookies
Chrome: Settings → Privacy → Clear browsing data Firefox: Settings → Privacy → Clear Data -
Access web UI
http://localhost:8096 -
Log in again
- Enter username/password
- Client will get new token
- WebSocket should connect successfully
-
Verify in browser console
// F12 → Console // Should see: "WebSocket connection established"
Option 3: Check Startup Configuration
File: startup.json or environment configuration
Verify:
{
"EnableRemoteAccess": true,
"RequireHttps": false, // For local development
"BaseUrl": "",
"HttpServerPortNumber": 8096
}
Common issues:
- BaseUrl misconfigured
- RequireHttps forcing HTTP redirect
- Port conflicts
Debugging WebSocket Connections
Check Browser Console
Open Developer Tools (F12):
// Console tab - look for:
WebSocket connection to 'ws://localhost:8096/socket' failed:
Error during WebSocket handshake: Unexpected response code: 401
Network tab:
- Look for
/socketrequest - Check status code
- Check headers (should have Authorization or api_key)
Check Jellyfin Logs
File: log/log_*.txt
Good connection:
[INF] WS 127.0.0.1 request
[INF] WS 127.0.0.1 closed
Failed connection:
[WRN] Error processing request: Token is required. URL GET /socket
When to Worry
⚠️ Investigate If:
- Constant errors - Every few seconds
- Affects functionality - Real-time updates not working
- After fresh install - Can't connect at all
- All clients failing - Not just one browser
✅ Ignore If:
- Occasional - Happens rarely
- No impact - Everything works fine
- Development only - Testing/debugging
- Browser extensions - External tools probing
Security Implications
✅ Good Security Practice
The "Token is required" error shows that:
- ✅ Authentication is enforced
- ✅ Unauthorized access is blocked
- ✅ Security middleware is working
- ✅ WebSocket endpoints are protected
If You Disable Authentication (DON'T!)
Never do this:
// BAD - Don't remove authentication check
if (!authorizationInfo.IsAuthenticated)
{
// Don't comment this out!
// throw new SecurityException("Token is required");
}
Why not:
- Anyone can connect to WebSocket
- Privacy violation
- Data leak
- Security vulnerability
Client Integration Guide
For Developers Building Jellyfin Clients
Correct WebSocket connection:
// Step 1: Get API token (after login)
const accessToken = jellyfinApi.getAccessToken();
// Step 2: Connect with token
const wsUrl = `ws://server:8096/socket?api_key=${accessToken}`;
const ws = new WebSocket(wsUrl);
// Step 3: Handle connection
ws.onopen = () => console.log('Connected');
ws.onmessage = (event) => console.log('Message:', event.data);
ws.onerror = (error) => console.error('Error:', error);
Alternative (Authorization header):
const ws = new WebSocket('ws://server:8096/socket');
ws.onopen = () => {
// Send authentication message
ws.send(JSON.stringify({
MessageType: 'Authenticate',
Data: accessToken
}));
};
Configuration Options
Option A: Log Level Adjustment (Recommended)
Reduce noise from failed connection attempts:
File: Jellyfin.Server/appsettings.json or startup.json
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Jellyfin.Api.Middleware.ExceptionMiddleware": "Error",
"Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware": "Error"
}
}
}
}
Effect:
- Security exceptions logged at Error level only
- Reduces log noise
- Still captures important errors
Option B: Custom WebSocket Authentication
If you need different auth logic (not recommended):
Modify WebSocketManager.cs:
// Allow anonymous for specific scenarios (NOT RECOMMENDED)
if (context.Request.Path == "/socket/anonymous")
{
// Skip authentication
}
Common Scenarios
Scenario 1: Browser Dev Tools
What happens:
- Open F12 dev tools
- Browser auto-tests WebSocket endpoint
- No token provided
- Error logged
Solution: Ignore - normal browser behavior
Scenario 2: Fresh Installation
What happens:
- First run of Jellyfin
- No users logged in yet
- Web UI tries to connect WebSocket
- Error logged until first login
Solution: Complete setup wizard and log in
Scenario 3: Session Timeout
What happens:
- User logged in previously
- Session expired (default: 24 hours)
- WebSocket reconnect fails
- Error logged
Solution: User re-authenticates automatically or manually
Scenario 4: Reverse Proxy Issues
What happens:
- Jellyfin behind reverse proxy (nginx, Apache)
- WebSocket headers not forwarded correctly
- Token not reaching Jellyfin
- Error logged
Solution: Configure reverse proxy to forward WebSocket headers
nginx example:
location /socket {
proxy_pass http://jellyfin:8096;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
}
Monitoring
Normal Operation
Expected log pattern:
[INF] WS 192.168.1.100 request
[INF] WS 192.168.1.100 closed
[INF] WS 192.168.1.101 request
Occasional failed attempts:
[WRN] Error processing request: Token is required. URL GET /socket
↑ This is fine if occasional
Problem Indicators
Constant errors (every few seconds):
[WRN] Error processing request: Token is required. URL GET /socket
[WRN] Error processing request: Token is required. URL GET /socket
[WRN] Error processing request: Token is required. URL GET /socket
...
↑ Investigate client authentication
Summary
Error: Token is required. URL GET /socket
Cause: Unauthenticated WebSocket connection attempt
Status: ✅ Expected behavior (security working)
Action Required: None (unless affecting functionality)
When to Ignore ✅
- Occasional occurrence
- No functionality impact
- Normal operation otherwise
When to Investigate ⚠️
- Constant/frequent errors
- Real-time updates not working
- After fresh install or configuration change
Related Files
WebSocketHandlerMiddleware.cs- Middleware entry pointWebSocketManager.cs- Authentication checkExceptionMiddleware.cs- Error logging
Quick Checklist
If this error concerns you, check:
- Can you access web UI? (http://localhost:8096)
- Can you log in?
- Do real-time updates work?
- Is this happening constantly or occasionally?
- Any reverse proxy in use?
If all above are OK → Ignore the error ✅
Conclusion: This is a security feature working correctly. The error logs unauthenticated connection attempts, which is expected and normal in web environments.
✅ No fix needed - security is working as designed!