~ knotless Search/
↑↓ move↵ open⇧↵ all results

grain.social/grain

photography-focused photo sharing platform

grain.social
1 collaborator
0
2

Photos post on PDSes that still require alt

Merged
Merged chadtmiller.com asked to merge into main from grain.social/grain:fix/photo-alt-always

What changes

Every photo the web app and the appview write now carries alt, an empty string when there is no description: create, gallery edit (new and replaced photos), Instagram import, and the private and pool gallery endpoints, which group create goes through. Nothing changes on screen. Readers treat an empty alt as none, so no ALT badge appears. AGENTS.md records the rule.

Why

People on many PDSes cannot post a photo without a description. They get XRPC dev.hatk.applyWrites failed: 500, reported at https://github.com/grainsocial/grain/issues/24.

The PDS refuses the write with Invalid social.grain.photo record: Missing required key "alt". @atproto/pds validates against schemas compiled into the server (validateRecord in packages/pds/src/repo/prepare.ts, listed in packages/pds/lexicons.json), not the ones grain.social publishes. Its copy of social.grain.photo requires alt, so publishing the relaxed schema on Oct 31 could not reach these servers.

Prod logs show 252 refusals across 14 accounts from Nov 2 to Nov 6, still arriving: 10 accounts on Bluesky hosts, 3 on selfhosted.social, 1 on pds.mcmanus.tech. 10 of the 14 had no photo in their repo dated since Oct 31 when checked on Nov 6.

An empty alt passes both the bundled copy and the published schema, and works today on every host. validate: false would also get past the check but turns off validation altogether. Asking Bluesky to update its copy is still worth doing, but each host then has to upgrade.

How it was checked

Read each write site and each reader of alt in app/ and server/. No test in test/ mentions alt, and none was added: the web write sites are inline in Svelte pages with no unit harness. Left to CI: type check and tests. Not tried in a browser or against a refusing PDS, since test posts reach production.

Shortcomings

  • Once this deploys, a post without a description from a Bluesky-hosted account is the real proof. Watch for "op":"refused" with required key in the logs.
  • The iOS and Android apps omit alt the same way and need their own change and release.
  • feature/rust has the same write sites under web/, and crates/grain-serve/src/spaces/pool.rs.
  • morel reports the same version as hosts that refuse, yet accepted two photos without alt. That is unexplained.
  • Deployed Bluesky hosts report 4744b4a; the schema and validator were read at atproto main, not at that commit. The error text matches this code exactly.

Review

A quick look. The reasoning is in the AGENTS.md section.

🤖 Generated with Claude Code

Approved

This makes every social.grain.photo write send alt, as an empty string when there is no description. That covers create, gallery edit (new and replaced photos), Instagram import, and the private and pool gallery endpoints. I searched app/ and server/ for other write sites and found none, so the coverage is complete. The alt || '' form is correct. I didn't check how readers treat an empty alt; I'm taking the PR's word that no ALT badge appears. The AGENTS.md section matches the change. I couldn't run it against a refusing PDS, so the real proof is the post-deploy log check the author already named. Approving.

Merged as ae0cb3a