TLDR: I needed to pass the --daemonize flag to gnome-keyring-daemon.
I had /usr/bin/gnome-keyring-daemon --start --components=gpg,pkcs11,secrets,ssh in my .xinitrc.
Adding the --daemonize argument appears to have resolved this.
/usr/bin/gnome-keyring-daemon --daemonize --start --components=gpg,pkcs11,secrets,ssh
Below is a hodge-podge of troubleshooting steps I took to resolve this in case you're experiencing a similar problem but not quite exactly the same.
I started with a bag of keywords that I figured were relevant: gpg, keyring, gpg-agent, pinentry, gpg password prompt.
Search the output of journalctl -xe for relevant-looking information. In this case, I saw:
Failed to lookup password for key <...> with secret service: Error
calling StartServiceByName for org.freedesktop.secrets...>
That gave me another keyword to search for: org.freedesktop.secrets. Looking in journalctl output for that led me to another entry:
dbus-daemon[2210]: [session uid=1000 pid=2208] Failed to activate service 'org.freedesktop.secrets': timed out (service_start_timeout=120000ms)
That gave me another keyword... dbus-daemon.
I used dbus-monitor to see what was being sent over DBus and read any error output.
I also sent a message to DBus to see if org.freedesktop.secrets was running. (https://rtfm.co.ua/en/what-is-linux-keyring-gnome-keyring-secret-service-and-d-bus/)
dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames
...
string "org.freedesktop.secrets"
...
Everything pointed to the org.freedesktop.secrets service not running.
How are gpg-agent, org.freedesktop.secrets, and dbus-daemon connected?
gpg-agent talks to a "keyring" over "DBus". In my case, my keyring was gnome-keyring-daemon.