navidrome/navidrome · error
Internal Server Error
Error message
Internal Server Error
What it means
GetTranscodeStream logs 'Error retrieving media file' and writes plain-text 'Internal Server Error' (HTTP 500) when api.ds.MediaFile(ctx).Get(mediaID) returns an error that is NOT model.ErrNotFound. The 404 path is reserved for missing records; any other failure (DB down, connection refused, context canceled, corruption) lands here.
Source
Thrown at server/subsonic/transcode.go:401
transcodeParamsToken, err := p.String("transcodeParams")
if err != nil {
http.Error(w, "Bad Request", http.StatusBadRequest)
return nil, nil
}
if !isValidMediaType(mediaType) {
http.Error(w, "Bad Request", http.StatusBadRequest)
return nil, nil
}
// Fetch the media file
mf, err := api.ds.MediaFile(ctx).Get(mediaID)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
http.Error(w, "Not Found", http.StatusNotFound)
} else {
log.Error(ctx, "Error retrieving media file", "mediaID", mediaID, err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
return nil, nil
}
// Validate the token and resolve streaming parameters
streamReq, err := api.transcodeDecision.ResolveRequestFromToken(ctx, transcodeParamsToken, mf, p.IntOr("offset", 0))
if err != nil {
switch {
case errors.Is(err, stream.ErrTokenInvalid), errors.Is(err, stream.ErrTokenStale):
log.Warn(ctx, "Invalid or stale transcode token", "mediaID", mediaID, err)
http.Error(w, "Gone", http.StatusGone)
default:
log.Error(ctx, "Error validating transcode params", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
return nil, nil
}
View on GitHub (pinned to 4ed7494a32)
Solutions
- Check server logs for the accompanying 'Error retrieving media file' entry to see the underlying error
- Verify the database backend is reachable and healthy (DB connection settings, service status)
- For SQLite, ensure no other process holds a conflicting lock and the file is writable
- Check disk space and complete any pending schema migrations, then retry
Defensive patterns
Strategy: retry
Validate before calling
// Preflight: cheap health check of the server before batch streaming
resp, err := http.Get(serverURL + "/ping")
if err != nil || resp.StatusCode != 200 {
return fmt.Errorf("server or database unavailable: %v", err)
} Try / catch
resp, err := client.Get(url)
if err != nil { return err }
if resp.StatusCode == http.StatusInternalServerError {
// transient server/DB failure: retry with backoff
return retryWithBackoff(3, 2*time.Second, doStream)
} Prevention
- Treat 500 during streaming as transient and retry with capped exponential backoff
- Monitor server health/DB connectivity before large batch operations
- Ensure backups don't hold DB locks during playback (SQLite)
- Keep the server upgraded with completed migrations
When it happens
Trigger: Database unavailable or restarting during a request; DB query fails (disk full, locked SQLite file, connection pool exhausted); request context canceled mid-query; schema mismatch after an incomplete upgrade.
Common situations: SQLite file locked by a backup process; Postgres container down; running the server while a migration is in flight; disk I/O errors on the DB volume.
Understand the failure class
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
Related errors
AI-assisted analysis of navidrome/navidrome@4ed7494a32 (2026-09-01).
Data as JSON: /api/errors/454da000b4a88ab9.
Report an issue: GitHub.