fix(downloads): don't classify per-item download 404s as source-level Not Found
gallery-dl logs `[download][error] Failed to download <file>.part` when a single post attachment's media URL expires or is deleted, then recovers and proceeds with the rest of the run. Our error categorizer was letting a urllib3 debug line like `"HEAD /media-u/v3/<id> HTTP/1.1" 404 0` match the NOT_FOUND_PATTERNS list, flagging the whole source as deleted even though gallery-dl kept downloading subsequent items successfully. Adds "failed to download" to the per-item allowlist so the mask flips when skip activity is present, matching the shape of the campaign-ID fix. Total-failure runs still classify as failures. Also renames the Download Details modal's "Error Log" panel to "Verbose Log (stderr)" — gallery-dl's `-v` flag sends all logging (including [debug] lines) to stderr, so the original label was misleading. Drops the blanket red text color for the same reason.
This commit is contained in:
@@ -441,11 +441,15 @@ class GalleryDLService:
|
||||
# - "failed to extract campaign id": logged when the vanity-URL HTML path
|
||||
# fails, but gallery-dl falls back to the /cw/<vanity> redirect and
|
||||
# recovers the campaign_id on its own.
|
||||
# - "failed to download": per-item download failure (e.g., a single
|
||||
# Patreon attachment whose media URL expired / was deleted). The
|
||||
# downloader logs [download][error] and moves to the next item.
|
||||
if has_actual_error and (skip_line_count > 0 or has_skip_text):
|
||||
per_item_patterns = [
|
||||
"not allowed to view",
|
||||
"unable to get post",
|
||||
"failed to extract campaign id",
|
||||
"failed to download",
|
||||
]
|
||||
error_lines = [
|
||||
line for line in combined.split('\n')
|
||||
|
||||
@@ -56,3 +56,40 @@ def test_patreon_campaign_id_error_alongside_real_error_still_fails():
|
||||
error_type, _message = service._categorize_error(1, stdout, stderr)
|
||||
|
||||
assert error_type == ErrorType.AUTH_ERROR
|
||||
|
||||
|
||||
def test_patreon_per_item_download_404_with_skips_is_no_new_content():
|
||||
"""Per-item 'Failed to download' + urllib3 404 HEAD + skips → no_new_content.
|
||||
|
||||
Real-world trigger: a Patreon post's media URL (e.g., /media-u/v3/<id>)
|
||||
expired or was deleted. gallery-dl logs [download][error] and moves on;
|
||||
other items skip cleanly. We shouldn't classify the whole source NOT_FOUND
|
||||
just because one attachment 404'd.
|
||||
"""
|
||||
service = _make_service()
|
||||
stderr = (
|
||||
"[download][error] Failed to download 02_46004845.part\n"
|
||||
'[urllib3.connectionpool][debug] "HEAD /media-u/v3/46004845 HTTP/1.1" 404 0\n'
|
||||
"[downloader.http][warning] '404 OK' for 'https://www.patreon.com/media-u/v3/46004845'\n"
|
||||
"[download][error] Failed to download 03_46004845.part\n"
|
||||
"[patreon][debug] skipping https://c10.patreonusercontent.com/4/patreon-media/p/post/30953341/.../1.png (abc image_large)\n"
|
||||
)
|
||||
stdout = ""
|
||||
|
||||
error_type, _message = service._categorize_error(1, stdout, stderr)
|
||||
|
||||
assert error_type == ErrorType.NO_NEW_CONTENT
|
||||
|
||||
|
||||
def test_patreon_per_item_download_failure_without_skips_still_fails():
|
||||
"""Same 'Failed to download' error but no skip activity → real failure."""
|
||||
service = _make_service()
|
||||
stderr = (
|
||||
"[download][error] Failed to download 02_46004845.part\n"
|
||||
'[urllib3.connectionpool][debug] "HEAD /media-u/v3/46004845 HTTP/1.1" 404 0\n'
|
||||
)
|
||||
stdout = ""
|
||||
|
||||
error_type, _message = service._categorize_error(1, stdout, stderr)
|
||||
|
||||
assert error_type != ErrorType.NO_NEW_CONTENT
|
||||
|
||||
@@ -334,9 +334,9 @@
|
||||
</v-expansion-panel-text>
|
||||
</v-expansion-panel>
|
||||
<v-expansion-panel v-if="selectedDownload.metadata.stderr">
|
||||
<v-expansion-panel-title>Error Log</v-expansion-panel-title>
|
||||
<v-expansion-panel-title>Verbose Log (stderr)</v-expansion-panel-title>
|
||||
<v-expansion-panel-text>
|
||||
<pre class="text-caption text-error" style="white-space: pre-wrap; max-height: 300px; overflow: auto">{{ selectedDownload.metadata.stderr }}</pre>
|
||||
<pre class="text-caption" style="white-space: pre-wrap; max-height: 300px; overflow: auto">{{ selectedDownload.metadata.stderr }}</pre>
|
||||
</v-expansion-panel-text>
|
||||
</v-expansion-panel>
|
||||
</v-expansion-panels>
|
||||
|
||||
Reference in New Issue
Block a user