Version 2.10.1: Problems with authority record that cannot be deleted.

25 views
Skip to first unread message

Carolyn Sullivan

unread,
Sep 2, 2026, 4:19:42 PM (yesterday) Sep 2
to AtoM Users
Hello all,

I am trying to delete this authority record: 

When I do that, I get this error:
2026-09-02_500Error.png
I tried rebuilding the nested set, repopulating the search index, restarting nginx, restarting php8.3-fpm, php symfony cc, sudo systemctl restart memcached.  None of these worked.

I then tried sudo -u www-data php symfony tools:data-integrity-repair /home/myusername/report_2026-09-02.csv --mode=fix

as recommended by:


This didn't work, it failed to output a csv with data errors for me, and I got the following output:

PHP Fatal error:  Uncaught TypeError: fputcsv(): Argument #1 ($stream) must be of type resource, false given in /usr/share/nginx/atom/lib/task/tools/dataIntegrityRepairTask.class.php:253

Stack trace:

#0 /usr/share/nginx/atom/lib/task/tools/dataIntegrityRepairTask.class.php(253): fputcsv()

#1 /usr/share/nginx/atom/lib/task/tools/dataIntegrityRepairTask.class.php(198): dataIntegrityRepairTask->report()

#2 /usr/share/nginx/atom/lib/task/tools/dataIntegrityRepairTask.class.php(63): dataIntegrityRepairTask->performDataIntegrityChecks()

#3 /usr/share/nginx/atom/vendor/symfony/lib/task/sfBaseTask.class.php(70): dataIntegrityRepairTask->execute()

#4 /usr/share/nginx/atom/vendor/symfony/lib/task/sfTask.class.php(97): sfBaseTask->doRun()

#5 /usr/share/nginx/atom/vendor/symfony/lib/command/sfSymfonyCommandApplication.class.php(76): sfTask->runFromCLI()

#6 /usr/share/nginx/atom/vendor/symfony/lib/command/cli.php(20): sfSymfonyCommandApplication->run()

#7 /usr/share/nginx/atom/symfony(14): include('...')

#8 {main}

  thrown in /usr/share/nginx/atom/lib/task/tools/dataIntegrityRepairTask.class.php on line 253

 I assume I'm giving it the wrong argument, but I gave it a filepath, so I'm not sure what's the problem.  Any suggestions dearly appreciated.

Thanks,

Carolyn.


Daniel Lovegrove

unread,
Sep 2, 2026, 4:21:56 PM (yesterday) Sep 2
to AtoM Users
Hi Carolyn,

It would be helpful if you could share the NGINX server logs when trying to delete this authority. That log file should have more information about what exactly is going wrong.

Best,
-Daniel

Alberto Pereira

unread,
9:35 AM (12 hours ago) 9:35 AM
to ica-ato...@googlegroups.com
Hi,

So that error is on line 253, which is:
        fputcsv($csvFile, ['id', 'parent_id', 'slug', 'issue(s)']);

This is very likely a folder permissions issue. Even if you use sudo:

sudo -u www-data php symfony tools:data-integrity-repair /home/myusername/report_2026-09-02.csv --mode=fix

The sudo above only says to run the command as www-data, it doesn't give it sudo root permissions. So www-data does not have permissions to write in /home/myusername. Change the folder permissions (or path in the command) and it should work.

Regarding the first error, as Daniel said, further errors should pop up in nginx (or other web server running it) logs.

--
You received this message because you are subscribed to the Google Groups "AtoM Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ica-atom-user...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/ica-atom-users/019900d5-e08b-419c-9eb0-1e048053eec8n%40googlegroups.com.

Carolyn Sullivan

unread,
10:09 AM (11 hours ago) 10:09 AM
to AtoM Users
Thanks folks, the issue with running the data integrity task was indeed a folder permissions issue.  With regard to the initial problem, checking error.log in /var/log/nginx , I see:
2026-09-03_nginxlogs.png
Is there anything useful in this message?  Incidentally, I ALSO can't find the information object by that id, if I do a 'SELECT * FROM information_object WHERE id=380823;', it pulls up zero results.  I'm pretty sure you're supposed to delete entries from the information_object table if you want a cascading delete to other tables where the entry occurs, but at this point, should I just delete open-6 from the slug table?

Alberto Pereira

unread,
11:04 AM (10 hours ago) 11:04 AM
to ica-ato...@googlegroups.com
Did you run the data integrity task again? After that, you should repopulate the index (php symfony search:populate)

Carolyn Sullivan

unread,
11:19 AM (10 hours ago) 11:19 AM
to AtoM Users
I did.  The issue doesn't show up in the report generated.

Johan Pieterse

unread,
11:29 AM (10 hours ago) 11:29 AM
to AtoM Users
Hi Carolyn,

A clean integrity report is expected here, and it tells you less than it looks like it does. That task cannot see authority records at all.

Every check it runs is scoped to descriptions and terms. In 2.10 the "invalid descriptions" query in lib/task/tools/dataIntegrityRepairTask.class.php ends:

    WHERE class_name="QubitInformationObject"
    AND object_id NOT IN (SELECT id FROM information_object);

and the checks above it all select FROM information_object or information_object_i18n, with one UPDATE against term. There is not a single query touching the actor tables. So a clean report rules out a broken description tree and says nothing whatsoever about open-6 if open-6 is an authority record. Worth knowing before you spend more time on that task, and also worth knowing that --mode=fix is safely scoped by that class_name filter, so it was never going to touch your authority records either way.

That is probably also why the id lookup came back empty. If 380823 is the authority record itself, it lives in actor, not information_object, and zero rows there is normal rather than a sign of corruption. First thing I would
confirm:

    SELECT s.slug, s.object_id, o.class_name
    FROM slug s
    LEFT JOIN object o ON o.id = s.object_id
    WHERE s.slug = 'open-6';

If class_name comes back QubitActor, call that id X and check the record is structurally whole:

    SELECT (SELECT COUNT(*) FROM object     WHERE id = X) AS object_row,
           (SELECT COUNT(*) FROM actor      WHERE id = X) AS actor_row,
           (SELECT COUNT(*) FROM actor_i18n WHERE id = X) AS i18n_rows;

Then hunt the dangling reference, which is what I would expect to be behind a
500 on delete. Deleting an actor cascades through its events and relations, and if one of those points at an object that no longer exists, the cascade hits a null and dies:

    -- events tying this actor to a description that is gone
    SELECT e.id AS event_id, e.object_id AS missing_object
    FROM event e
    LEFT JOIN object o ON o.id = e.object_id
    WHERE e.actor_id = X AND e.object_id IS NOT NULL AND o.id IS NULL;

    -- relations with a dangling end
    SELECT r.id AS relation_id, r.subject_id, r.object_id
    FROM relation r
    LEFT JOIN object s ON s.id = r.subject_id
    LEFT JOIN object t ON t.id = r.object_id
    WHERE (r.subject_id = X OR r.object_id = X)
      AND (s.id IS NULL OR t.id IS NULL);

    -- actor nested set and parentage
    SELECT id, parent_id, lft, rgt FROM actor WHERE id = X OR parent_id = X;

If one of those returns rows, that is your culprit. Take a dump of the affected tables first, delete the dangling rows, and then delete the authority record through the user interface so the normal cascade runs. Rebuild with search:populate afterwards.

On your last question: please do not delete open-6 from the slug table on its own. It removes the URL and nothing else. The object, actor and actor_i18n rows and every relation stay exactly where they are, so you end up with a record that is unreachable, still broken, and now much harder to find again. The slug is the symptom rather than the problem. Cascading deletes in AtoM are driven from the object table via the Propel model, not from information_object, and for an authority record information_object is not involved at all.

The other thing still missing is the actual text of the error. Daniel and Alberto both asked for it and the screenshots do not let anyone read the stack trace, which is where the answer almost certainly is. Something like:

    sudo tail -n 100 /var/log/nginx/error.log

pasted as text will show the exception class, file and line. An integrity constraint violation and a null dereference look identical from the browser and need completely different fixes, so that one paste probably saves another round of guessing.

One last thing worth raising upstream, since you hit it: at line 253 the task calls fputcsv() on the result of fopen() without checking it. When the path is not writable, fopen() returns false and you get the TypeError you saw instead of a readable "cannot open file for writing" message. Alberto diagnosed it correctly from the symptom, but the next person will lose the same twenty minutes. Might be worth an issue.

Best regards,
Dr Johan Pieterse
The Archive and Heritage Group
Reply all
Reply to author
Forward
0 new messages