SubtitleEdit/subtitleedit · error · FileNotFoundException
The requested URL was not found: {url}
Error message
The requested URL was not found: {url} What it means
Thrown by DownloadHelper.DownloadFileAsync when the HTTP response status is 404 NotFound. Rather than letting EnsureSuccessStatusCode raise a generic HttpRequestException, the helper detects 404 specifically and throws FileNotFoundException with the offending URL. This distinguishes 'the artifact does not exist upstream' from transient network errors so callers do not waste retry budget on a permanent condition.
Source
Thrown at src/ui/Logic/Download/DownloadHelper.cs:93
}
else if (currentPosition > startPosition && destination.CanSeek)
{
// No Range header will be sent, so the server returns the file from
// byte 0 - rewind the partial bytes from the failed attempt, otherwise
// the full body would be appended after them and corrupt the download.
destination.Seek(startPosition, SeekOrigin.Begin);
destination.SetLength(startPosition);
currentPosition = startPosition;
}
using var response = await httpClient.SendAsync(
request,
HttpCompletionOption.ResponseHeadersRead,
cts.Token).ConfigureAwait(false);
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
{
throw new FileNotFoundException($"The requested URL was not found: {url}");
}
response.EnsureSuccessStatusCode();
// Get total size from headers
if (totalBytes == null)
{
totalBytes = response.Content.Headers.ContentLength;
// For range requests, get total from Content-Range header
if (response.Content.Headers.ContentRange != null)
{
totalBytes = response.Content.Headers.ContentRange.Length;
}
}
var totalReadBytes = currentPosition; // Start from current position
View on GitHub (pinned to 17a9f07487)
Solutions
- Open the {url} from the error in a browser/curl to confirm it 404s upstream — if so, the asset is missing or moved.
- Update the service's ReleaseTag / BaseUrl / file-name constant to the release that actually contains the asset.
- If the URL looks correct, verify the host is reachable and not redirecting to a 404 login/CDN edge.
- Re-run with verbose HttpClient logging to capture the resolved URL and any redirect chain.
Example fix
// before: stale release tag yields 404 private const string ReleaseTag = "v1.0"; // after: pin to release that ships the asset private const string ReleaseTag = "v1.4.2";
Defensive patterns
Strategy: validation
Validate before calling
// Probe the URL with a HEAD before invoking the download
using var head = await httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, url), ct);
if (head.StatusCode == HttpStatusCode.NotFound)
throw new InvalidOperationException($"Asset missing upstream: {url}"); Try / catch
try { await DownloadHelper.DownloadFileAsync(http, url, fs, progress, ct); }
catch (FileNotFoundException ex) when (ex.Message.Contains("URL was not found"))
{ _logger.Error("Upstream 404 for {Url} — release tag or asset name is stale.", url); throw; } Prevention
- Treat a 404 as a permanent failure (the helper already excludes it from retries).
- Keep ReleaseTag/BaseUrl constants versioned with the upstream release.
- Add a smoke-test that HEADs each known asset URL in CI.
When it happens
Trigger: Any Get request inside DownloadFileAsync returns HTTP 404 — wrong release tag in the URL, asset renamed/removed from the GitHub release, wrong version pinned in the service's URL constant, or the CDN path was restructured. Note: the retry loop's catch filter excludes FileNotFoundException, so a 404 does NOT consume retries; it propagates immediately.
Common situations: Upstream GitHub release asset was renamed or deleted; ReleaseTag/BaseUrl constant is stale after an upgrade; typo in the assembled URL; mirror returned 404 because the file was unpublished; rate-limited request that the server answered with 404 instead of 403.
Related errors
- Dictionary download failed: {url}
- Download incomplete: expected {totalBytes} bytes, received {
- Failed to download file after {maxRetries} attempts. URL: {u
- Downloaded yt-dlp ({assetName}) failed SHA-256 verification
- NameList: Unable to read name list file: {fileNameOrUrl}
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/5d4dc71ed7eb0c23.
Report an issue: GitHub.