Library pick — fixed
C1Picking a directly-uploaded library asset (one with no underlying media row) throws “could not link.” Confirmed against the live brand: its only image asset — logo.png — is exactly this case (source=uploaded, source_media_id = NULL). The fix reads the bytes server-side instead of HTTP self-fetching an access-controlled route.
Beforepick → dead-end
Brand logo
image ref still needed
Could not link that library asset — try uploading it instead.
The asset has no media row, so the client asks the server to materialize one. That route byte-reads the file by HTTP-fetching the access-controlled file path — which 403s in a server-to-server call. Materialize returns nothing → the toast.
client picks logo.png
sourceMedia = null → POST materialize-media → self-fetch /file/logo.png
→ 403 → 502
sourceMedia = null → POST materialize-media → self-fetch /file/logo.png
→ 403 → 502
Afterpick → linked
logo.png linked
image ref have · library
Reference linked from your library.
Materialize reads the asset's bytes server-side via the storage adapter with
overrideAccess — the user is already authorized for this brand (writer+). No self-fetch, no cookie forwarding, no origin guessing. Idempotent: it backfills sourceMedia so the next pick short-circuits.
client picks logo.png
sourceMedia = null → POST materialize-media → read bytes server-side
→ media row → linked
sourceMedia = null → POST materialize-media → read bytes server-side
→ media row → linked
Scope & safety. Only the materialize-media route changes — the same fix benefits every pick path that reuses it (image studio, carousel, the style-kit calibrate/pick flow), not just video. Authorization is unchanged (writer+ on the brand is still required before any byte read); we simply stop re-authorizing through a fragile server-to-server HTTP hop. A regression test covers a
sourceMedia=null asset producing a linkable media id without a self-fetch.