Skip to content

Hide project screenshots whose file is gone from storage - #10

Draft
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-self-driving/fixleaderboard-handle-missing-571877
Draft

posthog[bot] wants to merge 1 commit into
mainfrom
posthog-self-driving/fixleaderboard-handle-missing-571877

Conversation

@posthog

@posthog posthog Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Problem

  • Builders on /leaderboard and /buddy see broken image icons where project screenshots should be. The image requests return 404.
  • The pages check only blob.persisted?. That checks the database row, not the file. Production stores files on local disk, and the blob rows live in Postgres. When a file goes from disk, the row stays and the page still renders the image.
  • The same check is in the buddy invite, project and ship pages. On the ship page, a missing file let a builder ship with a screenshot that is not there.

Origin

  • Replay Vision
  • First signal: 2026-10-07
  • Inbox report: open
  • Likely cause: 476ecf9
  • Task started by: auto-start, after the report was rated P2 and ready to fix

Changes

  • New Project#stored_screenshot returns the screenshot only when the storage service has its file. Else it returns nil, and the page shows no image (or the "Add a screenshot" placeholder on the project page).
  • All five views and the leaderboard helper use it in place of the old check.
  • Project#ship! copies the old screenshot to a ship only when its file exists. Else the ship form asks for a new screenshot.
  • A missing file sends a screenshot_file_missing warning to PostHog Logs through the existing PosthogLog. This gives a count of missing files, which the report could not get before.
Page Before After
/leaderboard, /buddy, buddy invite Broken image No image
Project page Broken image "Add a screenshot" placeholder
Ship page Broken preview, ship can keep a missing file Asks for a new screenshot

Warning

This PR does not fix the root cause. If the host does not keep /rails/storage across redeploys, uploaded files are still lost. config/deploy.yml mounts the wrong_tool_storage volume, but somebody with host access must confirm that the host uses it, or move Active Storage to a durable service such as S3.

Note

The check costs one File.exist? call per screenshot on the Disk service. The leaderboard rows are also built for the sidebar on the project page. If Active Storage moves to S3, each check becomes a HEAD request, so revisit this check then.

Tests

  • New model test: stored_screenshot is nil after the file is deleted from storage.
  • The leaderboard screenshot test now deletes the file and checks that the leaderboard has no image and the project page shows the placeholder.
  • Ran: bin/rails test (137 runs, 0 failures) and bin/rubocop (no offenses), on Ruby 3.2.3 because the sandbox has no Ruby 3.4.3.
  • Not run: system tests (no Chrome in the sandbox).

Agent context

  • I did not use a client-side onerror handler. It still sends the failing request, and it needs a Stimulus controller on each image.
  • I did not confirm the file loss on the host. The sandbox has no access to it.
  • I did not see the pages in a browser. The controller test checks the rendered HTML: no img tag for a missing file.

Created with PostHog Desktop from this inbox report.

🤖 Generated with Claude Code

The leaderboard, buddy, buddy invite, project and ship pages checked only that the screenshot's blob row exists. When the file is gone from local-disk storage, the row stays and the page shows a broken image. Project#stored_screenshot also checks the file, and logs screenshot_file_missing to PostHog Logs when it is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Generated-By: PostHog Desktop
Task-Id: 5acce8a2-b26d-48b2-ac7a-fbb3ccaebe88

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.

0 participants