Skip to content

Log marker cleanup failures instead of swallowing them (#989) - #990

Open
vjpixel wants to merge 1 commit into
developfrom
feature/989-marker-cleanup-logging
Open

vjpixel wants to merge 1 commit into
developfrom
feature/989-marker-cleanup-logging

Conversation

@vjpixel

@vjpixel vjpixel commented Sep 17, 2026

Copy link
Copy Markdown
Member

Description

A marker upload first lands in storage under the uploader's own filename, because Marker.source has upload_to="markers/". generate_marker_variants then renames it to markers/<pk>/original.<ext> and deletes the original — but that delete was wrapped in a bare except Exception: pass labelled "non-critical cleanup".

It isn't non-critical. If the delete fails, the object stays publicly reachable under a name the uploader chose, and nothing anywhere records it: no log, no metric, no retry. That's the same privacy exposure @pablodiegoss described on #699 — it just happens on the failure path instead of the happy one.

Resolves (Issues)

Closes #989

General tasks performed

  • Narrowed the except from bare Exception to OSError and SuspiciousFileOperation.
  • Replaced pass with log.exception(...), naming the path left behind and the marker id, so it reaches Sentry.
  • Rewrote the comment to say why the cleanup matters, rather than calling it non-critical.
  • Added src/core/tests/test_marker_cleanup_logging.py — the happy path renames away from the user's filename; a failing storage.delete is logged and the upload still succeeds; a successful cleanup logs nothing.

Something the test surfaced

Django's get_valid_name sanitises but does not anonymise. An upload named Minha imagem #1.png reaches storage as markers/Minha_imagem_1.png — spaces become underscores and # is dropped, yet it is still recognisably the uploader's chosen name. The test asserts on the sanitised form, and there's a comment explaining why, so the next reader doesn't assume Django already solved this.

Deliberately unchanged: the failure still doesn't fail the upload, and there's no retry or sweeper. Making it visible is the fix this issue asks for; deciding whether to retry or queue the path for a later sweep is a design call for the maintainers.

Verification: full suite pytest src/core src/users src/blog passes — 275 passed. ruff format --diff src/ clean, zero I001, and ruff check actually drops from 93 findings on develop to 92 here, because removing the bare except also removes its BLE001 and S110.

Have you confirmed the application builds locally without error? See here.

  • Yes

🤖 Generated with Claude Code

https://claude.ai/code/session_01HXUw7kyELDu8ycGQxtaFbb


Generated by Claude Code

The marker upload lands in storage under the uploader's own filename before
generate_marker_variants renames it to markers/<pk>/original.<ext> and
deletes the original. That delete sat in a bare `except Exception: pass`, so
a storage failure left the user-named object in public storage with nothing
recording it.

Narrows the except to OSError and SuspiciousFileOperation and logs the
exception with the path left behind. The upload still succeeds either way.

Closes #989

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXUw7kyELDu8ycGQxtaFbb

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Marker cleanup swallows delete failures, leaving user-named files in public storage

2 participants