Very sorry, I briefly took my instance down thinking that I could somehow fix the problem on my own, unfortunately I am not seeing the replies to this post unless I view it on the original server...that's my bad. I did get the replies from rimu and others regarding the problem though, I appreciate very much that a fix for this issue is already in the works! May I ask how one would go about applying it, or would it just be a regular update?
PieFed help
It's seems right that we should have a local community to help us all with PieFed
Rules
Be kind! We're all learning
If rimu is fixing it the way I suspect he is, then it will just be a regular update. Since you are running docker, here is how to make sure you are updating where you want. No need to run any of this until he pops back in here and lets you know that he pushed a fix to the 1.5 branch.
# Prerequisite - navigate to the pyfedi folder
# Bring down the docker containers
docker compose down
# Wait for all the containers to stop
# Check to make sure you are on the 'v1.5.x' branch
git status
# You should see near the top of this output 'On branch v1.5.x'
# If it says a different branch name, then probably stop here and ask for help
# Feel free to hit up the matrix room or chat.piefed.social for more realtime support as well
# Pull the updates and start docker back up
./deploy-docker2.sh
Goodness, well that's certainly easy enough to handle, I'm glad that I did the Docker install after all ๐ Very impressive that a fix is on the way already as well, I will look forward to it as I've made a bunch of test posts that I've deleted on my instance and they are currently cluttering things up ๐
I will keep an eye on the thread for further developments, much appreciated once again!
Sorry, looks like the fix will have to come out in v1.6, available in a week or so.
In the meantime you can fix it manually by running this: (change postgres_container to your DB container)
docker exec -i postgres_container psql -U piefed piefed <<'SQL'
ALTER TABLE post_vote
DROP CONSTRAINT IF EXISTS post_vote_post_id_fkey,
ADD CONSTRAINT post_vote_post_id_fkey
FOREIGN KEY (post_id)
REFERENCES post(id)
ON DELETE CASCADE;
ALTER TABLE post_reply_vote
DROP CONSTRAINT IF EXISTS post_reply_vote_post_reply_id_fkey,
ADD CONSTRAINT post_reply_vote_post_reply_id_fkey
FOREIGN KEY (post_reply_id)
REFERENCES post_reply(id)
ON DELETE CASCADE;
SQL
I very much appreciate that a fix for this has been provided even before the official patch has been released, which I understand will be in a week or so with the release of 1.6. That's great news! In the meantime the deleted posts that I was having trouble purging seem to be gone. ๐
Looking forward to 1.6!
As an addendum, I did actually try creating and deleting some posts to give things a test run, looks like everything is working just fine ๐ I expect the patch will do the trick!
I've been able to pull the logs from the system, I think this is the error that occurs in the backend when trying to purge a post on my instance. I'm not sure what it means or why it's occurring, but it does seem to be logged every time I try to purge a deleted post.
piefed_app1 | [2026-01-27 00:58:31,192] ERROR in app: Exception on /post/51/purge [POST]
piefed_app1 | Traceback (most recent call last):
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
piefed_app1 | self.dialect.do_execute(
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~~~^
piefed_app1 | cursor, str_statement, effective_parameters, context
piefed_app1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
piefed_app1 | )
piefed_app1 | ^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 952, in do_execute
piefed_app1 | cursor.execute(statement, parameters)
piefed_app1 | ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
piefed_app1 | psycopg2.errors.ForeignKeyViolation: update or delete on table "post" violates foreign key constraint "post_vote_post_id_fkey" on table "post_vote"
piefed_app1 | DETAIL: Key (id)=(51) is still referenced from table "post_vote".
piefed_app1 |
piefed_app1 |
piefed_app1 | The above exception was the direct cause of the following exception:
piefed_app1 |
piefed_app1 | Traceback (most recent call last):
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/flask/app.py", line 1511, in wsgi_app
piefed_app1 | response = self.full_dispatch_request()
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/flask/app.py", line 919, in full_dispatch_request
piefed_app1 | rv = self.handle_user_exception(e)
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/flask/app.py", line 917, in full_dispatch_request
piefed_app1 | rv = self.dispatch_request()
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/flask/app.py", line 902, in dispatch_request
piefed_app1 | return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
piefed_app1 | File "/app/app/utils.py", line 1239, in decorated_view
piefed_app1 | return current_app.ensure_sync(func)(*args, **kwargs)
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
piefed_app1 | File "/app/app/post/routes.py", line 1178, in post_purge
piefed_app1 | db.session.commit()
piefed_app1 | ~~~~~~~~~~~~~~~~~^^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/scoping.py", line 597, in commit
piefed_app1 | return self._proxied.commit()
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~^^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 2030, in commit
piefed_app1 | trans.commit(_to_root=True)
piefed_app1 | ~~~~~~~~~~~~^^^^^^^^^^^^^^^
piefed_app1 | File "<string>", line 2, in commit
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go
piefed_app1 | ret_value = fn(self, *arg, **kw)
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1311, in commit
piefed_app1 | self._prepare_impl()
piefed_app1 | ~~~~~~~~~~~~~~~~~~^^
piefed_app1 | File "<string>", line 2, in _prepare_impl
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/state_changes.py", line 137, in _go
piefed_app1 | ret_value = fn(self, *arg, **kw)
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 1286, in _prepare_impl
piefed_app1 | self.session.flush()
piefed_app1 | ~~~~~~~~~~~~~~~~~~^^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4331, in flush
piefed_app1 | self._flush(objects)
piefed_app1 | ~~~~~~~~~~~^^^^^^^^^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4466, in _flush
piefed_app1 | with util.safe_reraise():
piefed_app1 | ~~~~~~~~~~~~~~~~~^^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 224, in __exit__
piefed_app1 | raise exc_value.with_traceback(exc_tb)
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/session.py", line 4427, in _flush
piefed_app1 | flush_context.execute()
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~^^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute
piefed_app1 | rec.execute(self)
piefed_app1 | ~~~~~~~~~~~^^^^^^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/unitofwork.py", line 679, in execute
piefed_app1 | util.preloaded.orm_persistence.delete_obj(
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
piefed_app1 | self.mapper,
piefed_app1 | ^^^^^^^^^^^^
piefed_app1 | uow.states_for_mapper_hierarchy(self.mapper, True, False),
piefed_app1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
piefed_app1 | uow,
piefed_app1 | ^^^^
piefed_app1 | )
piefed_app1 | ^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 193, in delete_obj
piefed_app1 | _emit_delete_statements(
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~~~^
piefed_app1 | base_mapper,
piefed_app1 | ^^^^^^^^^^^^
piefed_app1 | ...<3 lines>...
piefed_app1 | delete,
piefed_app1 | ^^^^^^^
piefed_app1 | )
piefed_app1 | ^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/orm/persistence.py", line 1471, in _emit_delete_statements
piefed_app1 | c = connection.execute(
piefed_app1 | statement, del_objects, execution_options=execution_options
piefed_app1 | )
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1419, in execute
piefed_app1 | return meth(
piefed_app1 | self,
piefed_app1 | distilled_parameters,
piefed_app1 | execution_options or NO_OPTIONS,
piefed_app1 | )
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/sql/elements.py", line 527, in _execute_on_connection
piefed_app1 | return connection._execute_clauseelement(
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
piefed_app1 | self, distilled_params, execution_options
piefed_app1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
piefed_app1 | )
piefed_app1 | ^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement
piefed_app1 | ret = self._execute_context(
piefed_app1 | dialect,
piefed_app1 | ...<8 lines>...
piefed_app1 | cache_hit=cache_hit,
piefed_app1 | )
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context
piefed_app1 | return self._exec_single_context(
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~~~~~^
piefed_app1 | dialect, context, statement, parameters
piefed_app1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
piefed_app1 | )
piefed_app1 | ^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context
piefed_app1 | self._handle_dbapi_exception(
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
piefed_app1 | e, str_statement, effective_parameters, cursor, context
piefed_app1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
piefed_app1 | )
piefed_app1 | ^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2363, in _handle_dbapi_exception
piefed_app1 | raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
piefed_app1 | self.dialect.do_execute(
piefed_app1 | ~~~~~~~~~~~~~~~~~~~~~~~^
piefed_app1 | cursor, str_statement, effective_parameters, context
piefed_app1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
piefed_app1 | )
piefed_app1 | ^
piefed_app1 | File "/usr/local/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 952, in do_execute
piefed_app1 | cursor.execute(statement, parameters)
piefed_app1 | ~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
piefed_app1 | sqlalchemy.exc.IntegrityError: (psycopg2.errors.ForeignKeyViolation) update or delete on table "post" violates foreign key constraint "post_vote_post_id_fkey" on table "post_vote"
piefed_app1 | DETAIL: Key (id)=(51) is still referenced from table "post_vote".
piefed_app1 |
piefed_app1 | [SQL: DELETE FROM post WHERE post.id = %(id)s]
piefed_app1 | [parameters: {'id': 51}]
piefed_app1 | (Background on this error at: https://sqlalche.me/e/20/gkpj)
Ah yes, I know this one. I wasn't sure how widespread it was but it seems worse than I hoped. I'll get a fix out shortly.
Basically, it is saying that it can't delete the post because that post's row in the database is still being referenced somewhere else in the database. In this case, it is being referenced by rows in the table where we store votes for the post.
This is the same issue that popped up recently for another user. For whatever reason, sometimes the database misses setting the deletes for post and comment votes to cascade properly. I tried and couldn't replicate the issue in my test environment. rimu is probably making a new database migration that will apply it again and that should fix it.
