Fixed.
It took some DB wrangling. I used the postgres docker image to mount the database:
docker run --name postgres_container_2 -e POSTGRES_PASSWORD=mysecretpassword -d -p 5432:5432 -v /var/discourse/shared/standalone/postgres_data:/var/lib/postgresql/data postgres:15
Then located the offending table row:
SELECT
tc.topic_id,
tc.answer_post_id,
tc.topic_timer_id,
tc.accepter_user_id,
tc.created_at,
tc.updated_at
FROM (
SELECT
tc.topic_id,
CAST(tc.value AS INTEGER) AS answer_post_id,
CAST(tc2.value AS INTEGER) AS topic_timer_id,
COALESCE(ua.acting_user_id, -1) AS accepter_user_id,
tc.created_at,
tc.updated_at,
ROW_NUMBER() OVER (PARTITION BY tc.topic_id ORDER BY tc.created_at ASC) AS rn_topic,
ROW_NUMBER() OVER (PARTITION BY CAST(tc.value AS INTEGER) ORDER BY tc.created_at ASC) AS rn_answer
FROM topic_custom_fields tc
LEFT JOIN topic_custom_fields tc2 ON tc2.topic_id = tc.topic_id AND tc2.name = 'solved_auto_close_topic_timer_id'
LEFT JOIN user_actions ua ON ua.target_topic_id = tc.topic_id AND ua.action_type = 15
WHERE tc.name = 'accepted_answer_post_id'
AND tc.id > 0
AND tc.id <= 0 + 10000
AND tc.value IS NULL
) tc
Once I’d ensured this selected just the row in the error, I changed the select to a DELETE, crossed my fingers and ./launcher rebuild app
.
After much time waiting for the image to build, I now have a happy community and a rebuilt site, security fixes included.
I don’t know what caused the row mentioned above to become invalid, but once it was removed, all is well.