Fatal PHP error b/c Symfony problems

The community help forum (help.nextcloud.com) is for home and non-enterprise users. Support is provided by other community members on a best effort / “as available” basis. All of those responding are volunteering their time to help you.

If you’re using Nextcloud in a business/critical setting, paid and SLA-based support services can be accessed via portal.nextcloud.com where Nextcloud engineers can help ensure your business keeps running smoothly.

Getting help

In order to help you as efficiently (and quickly!) as possible, please fill in as much of the below requested information as you can.

Before clicking submit: Please check if your query is already addressed via the following resources:

The Basics

  • Nextcloud Server version (e.g., 29.x.x):
    • 35.0.0 beta 3
  • Operating system and version (e.g., Ubuntu 24.04):
    • Debian 13.6 (Trixie)
  • Web server and version (e.g, Apache 2.4.25):
    • Nginx 1.31.3
  • PHP version (e.g, 8.3):
    • 8.4, all necessary and most recommended modules installed and enabled
  • Is this the first time you’ve seen this error? (Yes / No):
    • Yes
  • When did this problem seem to first start?
    • couple of days ago - don't remember exactly
  • Installation method (e.g. AlO, NCP, Bare Metal/Archive, etc.)
    • plain OS, installed via command line years ago and upgraded to every new version, incl. betas
  • Are you using CloudfIare, mod_security, or similar? (Yes / No)
    • no

Summary of the issue you are facing:

Trying to upgrade the apps results in a fatal PHP error:

sudo -u www-data php occ app:update --all
PHP Fatal error: Declaration of OCA\audioplayer\Command\Reset::execute(Symfony\Component\Console\Input\InputInterface $input, Symfony\Component\Console\Output\OutputInterface $output) must be compatible with Symfony\Component\Console\Command\Command::execute(Symfony\Component\Console\Input\InputInterface $input, Symfony\Component\Console\Output\OutputInterface $output): int in /var/www/nextcloud/apps/audioplayer/lib/Command/Reset.php on line 38

I tried to disable the audioplayer app, but the error comes again, caused by a different app. App list and NC config can’t be accessed via OCC, as they throw the same error.

Upgrade the NC server itself works flawlessly.

Any ideas how to solve this? I’ll be happy to provide additional info if needed

Steps to replicate it (hint: details matter!):

  1. issue the command above on the command line

Log entries

Nextcloud

{"reqId":"PFuq3aUxiK0k8vDbEgKz","level":3,"time":"2026-08-19T10:11:07+02:00","remoteAddr":"","user":"--","app":"PHP","method":"","url":"--","scriptName":"occ","message":"Declaration of OCA\\audioplayer\\Command\\Reset::execute(Symfony\\Component\\Console\\Input\\InputInterface $input, Symfony\\Component\\Console\\Output\\OutputInterface $output) must be compatible with Symfony\\Component\\Console\\Command\\Command::execute(Symfony\\Component\\Console\\Input\\InputInterface $input, Symfony\\Component\\Console\\Output\\OutputInterface $output): int at /var/www/nextcloud/apps/audioplayer/lib/Command/Reset.php#38","userAgent":"--","version":"35.0.0.4","occ_command":["occ","app:update"],"data":{"app":"PHP"}}

Web server / Reverse Proxy

The output of your Apache/nginx/system log in /var/log/____:

none

Configuration

Nextcloud

$CONFIG = array (
  'instanceid' => 'XXX',
  'serverid' => 42,
  'passwordsalt' => 'XXX',
  'secret' => 'XXX',
  'trusted_domains' => 
  array (
    0 => 'XXX',
    1 => 'XXX',
    2 => '192.168.XXX',
    3 => 'XXX',
    4 => '127.0.0.1',
  ),
  'datadirectory' => 'XXX',
  'dbtype' => 'mysql',
  'version' => '35.0.0.4',
  'overwrite.cli.url' => 'http://localhost',
  'dbname' => 'nextcloud',
  'dbhost' => 'localhost:/var/run/mysqld/mysqld.sock',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'XXX',
  'dbpassword' => 'XXX',
  'installed' => true,
  'activity_expire_days' => 14,
  'auth.bruteforce.protection.enabled' => true,
  'blacklisted_files' => 
  array (
    0 => '.htaccess',
    1 => 'Thumbs.db',
    2 => 'thumbs.db',
  ),
  'cron_log' => true,
  'enable_previews' => true,
  'enabledPreviewProviders' => 
  array (
    0 => 'OC\\Preview\\PNG',
    1 => 'OC\\Preview\\JPEG',
    2 => 'OC\\Preview\\GIF',
    3 => 'OC\\Preview\\BMP',
    4 => 'OC\\Preview\\XBitmap',
    5 => 'OC\\Preview\\Movie',
    6 => 'OC\\Preview\\PDF',
    7 => 'OC\\Preview\\MP3',
    8 => 'OC\\Preview\\TXT',
    9 => 'OC\\Preview\\MarkDown',
  ),
  'filesystem_check_changes' => 1,
  'filelocking.enabled' => 'true',
  'htaccess.RewriteBase' => '/',
  'integrity.check.disabled' => false,
  'knowledgebaseenabled' => false,
  'logfile' => 'nextcloud.log',
  'loglevel' => 0,
  'logtimezone' => 'Europe/Berlin',
  'log_rotate_size' => 104857600,
  'maintenance' => false,
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'redis' => 
  array (
    'host' => '/run/redis/redis.sock',
    'port' => 0,
    'timeout' => 0.0,
  ),
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'overwriteprotocol' => 'https',
  'preview_max_x' => 1024,
  'preview_max_y' => 768,
  'preview_max_scale_factor' => 1,
  'quota_include_external_storage' => false,
  'share_folder' => '/Shares',
  'skeletondirectory' => '',
  'theme' => '',
  'trashbin_retention_obligation' => 'auto, 7',
  'updater.release.channel' => 'beta',
  'mail_smtpmode' => 'sendmail',
  'mail_sendmailmode' => 'pipe',
  'mail_from_address' => 'nextcloud',
  'mail_domain' => 'XXX',
  'mail_smtpauthtype' => 'LOGIN',
  'mail_smtpauth' => 1,
  'mail_smtphost' => 'XXX',
  'mail_smtpport' => '587',
  'mail_smtpname' => 'XXX',
  'mail_smtppassword' => 'XXX',
  'mail_smtpsecure' => 'tls',
  'default_phone_region' => 'DE',
  'app_install_overwrite' => 
  array (
    0 => 'dicomviewer',
    2 => 'carnet',
    3 => 'onlyoffice',
    4 => 'richdocuments',
    5 => 'richdocumentscode',
    7 => 'files_photospheres',
    9 => 'audioplayer',
    10 => 'audioplayer_editor',
    12 => 'tasks',
    13 => 'ocsms',
    14 => 'files_trackdownloads',
    16 => 'twofactor_u2f',
    17 => 'checksum',
    18 => 'event_update_notification',
    19 => 'mindmap_app',
    20 => 'contacts',
    21 => 'deck',
    22 => 'spreed',
    23 => 'twofactor_webauthn',
    25 => 'previewgenerator',
    26 => 'calendar',
    27 => 'camerarawpreviews',
    28 => 'journeys',
    29 => 'imageconverter',
  ),
  'has_rebuilt_cache' => true,
  'maintenance_window_start' => 1,
);

This version is still under development.

You can try and disable as much apps as possible, if you are able to find some configuration that works and then report the issues to the specific apps.

Yeah, that’s not a great idea if that’s your production instance.

I’d strongly recommend staying on the stable channel and maintaining a separate instance if you want to test beta releases. And even then, it’s often a good idea to wait for the first few point releases before upgrading to a new major version on your production instance, especially if you’re using third-party apps, which are often not yet compatible when a new major version of Nextcloud is released.

Feeling a little befuddled that I’m being lectured for being willing to use the betas and report error I stumble upon - I didn’t complain about apps no longer working, just about the error that crashes the app update. Maybe the doesn’t work right now - but since it is a small installation with few users there’s not a big problem here.

Anyway - since disabling apps threw the same error with the next app in the list I figured there seems to be a major incompatibility issue which should be worth reporting. Maybe that was a false assumption, so I’ll go with @tflidd 's suggestion and report back about that.

MIght be that it is just something with the apps that is not compatible any more, and that it affects not just one app. But for new versions, that is also a point of going through the apps in case some interaction does not work any more.

I have a test setup using the beta versions as well. Luckily no major problems so far, and I use it quite a bit to play around. But it can happen that certain things do not work, especially apps.

Hi @Miyamoto,

your assumption was not false at all, and thanks for running the betas and reporting what you find. Here is what is happening.

The cause

Nextcloud 35 raises Symfony Console from 6.4 to 7: nextcloud/3rdparty#2550 for the dependency itself, nextcloud/server#62962 for the server side. That second one states the consequence in its own description:

Note that this will breaks some apps as execute now need to return an int, but:

  • This is a private interface in OC\Core
  • Fixing it in an app doesn’t break support for older version of NC
  • Most apps already have the correct signature

The return type arrived with Symfony 7, in symfony/symfony#50852:

// symfony/console 6.4
protected function execute(InputInterface $input, OutputInterface $output)
// symfony/console 7
protected function execute(InputInterface $input, OutputInterface $output): int

Once the parent declares : int, every override has to declare it too, or PHP aborts while the class is being loaded. Audioplayer 3.9.0 still has the old form, and this is exactly the line your log names:

Any app whose occ command overrides execute() without : int will abort the same way, and that is why disabling one app only moved the error to the next one.

So this is not a server issue and there is nothing to fix in your configuration.

Getting occ usable again

occ builds its command list from all installed apps, so a single bad signature takes down every occ call, including the ones you would need to disable the app. Moving the app directory out of the way is the way around that:

mkdir /var/www/parked
mv /var/www/nextcloud/apps/audioplayer /var/www/parked/

To find all candidates in one go instead of one crash at a time:

grep -rn "function execute(InputInterface" /var/www/nextcloud/apps/ | grep -v ": int"

Every hit is an app that will break occ on 35. Park those directories, then occ works again and you can disable the apps properly.

That second step is not optional. Moving a directory only takes the code out of the way, it does not tell Nextcloud anything — the app stays registered as enabled in the database, and the moment the directory comes back it loads again and you are exactly where you started. So for every app you parked:

occ app:disable audioplayer

Then you can move the directory back whenever you like, and it will sit there quietly until the app has a version that works.

Please report it to the app

This belongs in the audioplayer tracker as a bug, and it is worth being precise about what the bug is, because there are two.

The obvious one is the missing return type. That change was not sprung on anyone: it is written up under Critical changes in the developer manual, with a ready-made one-liner that fixes an entire app in a single pass. And per the note quoted above, applying it does not cost the app its support for older Nextcloud releases, so there is nothing to weigh up.

The less obvious one is why it reached you at all. Audioplayer declares max-version="99" in its info.xml. That is a compatibility promise for every Nextcloud release up to 99 — versions that did not exist when the line was written and that nobody could have tested against. The documented example for that element is a real, narrow range, min-version="31" max-version="32", and there is a reason for that: the field is what tells your server to keep an untested app switched off until the maintainer has actually looked. Set to 99, it never says no, and the first person to find out that the combination does not work is the user — not through a tidy “app disabled” notice, but through a dead occ and a fatal error in the log.

That is the part worth raising, calmly but clearly: the missing : int is a small oversight that happens, whereas a blanket max-version="99" is what turned it into your afternoon instead of the maintainer’s. I found no open issue about either point in the repository, so yours would be the first.

No need to write it all out again — link this post in the issue if it helps, the references above are all there.

Separate point: your app_install_overwrite

This one is not the cause of your crash, but it is worth cleaning up while you are in there. Because of that max-version="99", audioplayer would have loaded regardless of the list.

What the list actually does is skip the max-version check, and nothing else — AppManager::overwriteNextcloudRequirement():

/**
 * Overwrite the `max-version` requirement for this app.
 */
public function overwriteNextcloudRequirement(string $appId): void

It does not make an app compatible. It only removes the check that would have told you the app is not. It is also absent from config.sample.php, which is the list of settings meant for permanent use — this one is a switch for trying something out, not a setting to leave in place.

Your list holds 24 entries, and the gaps in the indices show it has been growing for years without ever being cleared. Several of them are shipped apps — contacts, calendar, deck, spreed, tasks, richdocuments — which never need an entry there. That check is the one thing standing between a major upgrade and a set of apps that were never tested against it, and right now it is switched off for two dozen of them.

The habit worth adopting: empty the array before an upgrade, especially before a beta, so the compatibility check is intact when it matters. After the upgrade, re-enable apps one at a time and force only the ones you actually need, which puts them back in the list deliberately rather than by accident. You can edit it out of config.php directly, no occ needed.

h.t.h.


ernolf

Grand, thanks for this detailed advice. I’m positive it’ll help my case, and I’ll be happy to report the issue to the apps affected.

And thanks for the advice regarding the app list - I’ll take a look at it, too.

EDIT: bug reports for audioplayer, journeys and carnet have been opened. Thanks again for the fast and detailed advice.

I didn’t say you shouldn’t test betas. I said I’d recommend doing so on a separate instance. But obviously, you can do whatever you want. After all, it’s your server. :wink:

Good for you. In that case, I guess you can safely ignore my recommendation. :wink:

But not everyone wants to deal with outages, and let’s put it this way: unlike with some other projects and software, when Nextcloud calls something a beta, it actually means beta. So I won’t stop pointing out here in the forum that beta releases shouldn’t be used on production servers, and if you want to be extra cautious, I’d even recommend waiting for the first few point releases before upgrading to a new major version.

You can see that as lecturing if you want, or simply as well-intentioned advice. At the end of the day, it’s your decision.

If you want the developers to be aware of it, it would be better to report those issues in the issue tracker of the respective apps, which you apparently did in the meantime. Thanks for that. :+1:

For anyone encountering similar error in other apps, run `find lib -iname ‘*.php’ -exec sed -i ‘s/function execute(InputInterface $input, OutputInterface $output) {/function execute(InputInterface $input, OutputInterface $output): int {/g’ {} \;` and submit the patch to the app :slight_smile:

See Critical changes — Nextcloud 35 Developer Manual for more details

this command should be executed within the app’s folder - correct?

yes :slight_smile: on each app folder. Btw I now submitted a pull request for both audiplayer and journeys

Thanks @carlschwan, and thanks for doing the Symfony 7 work in the first place. You wrote that section of the manual, and you also shipped the new attribute-based command interface alongside it, so apps do not have to extend a Symfony base class at all any more. That is the part that stops this from happening again on the next bump, and it is more than a version bump had to come with.

The one-liner is straight from that manual page, which I already linked to in my answer above, so the reporter can hand the maintainer the issue and the manual page together. I left the command itself out on purpose: this is the general support category and the person asking runs the instance, they do not maintain the app. A patch applied to apps/audioplayer/lib is also gone with the next app update and helps nobody else, so the path that actually ends this is the issue in the app tracker. Your one-liner belongs in that issue, it saves the maintainer the work of figuring out the fix.

But for anyone about to paste it into a terminal, two things:

Run it from the app directory. The lib in that find is a relative path, so from /var/www/nextcloud it would walk the server’s own lib/ instead of the app’s.

It matches literally. $input and $output as the parameter names, single spaces, and the { on the same line. files_scripts writes ) { with two spaces in all four of its commands, unchanged in its current release, which declares max-version="35". So the sed walks straight past an app that is going to carry the problem into 35.

Which brings me to the scope. The grep I posted further up was a quick survey with no patch instruction attached to it, and for that it was fine, but as the input for something that writes to files it is too wide. Under apps/ it also reaches vendored CLI libraries that occ never loads, bundled copies of Symfony’s own Command::execute(), Rector rule classes that carry the old signature as their fixture, and matches inside .phar files. Narrowing it to lib/ without vendor directories still leaves things like a Mapper::execute($sql, array $params = [], …) with no return type at all, an Interpreter::execute(Script $script, …), and php-scoper’d libraries under lib/Vendor/. execute() is a common method name, and adding : int to all of that would break more than it fixes.

Line-based matching cannot settle the wrapped case either. The server’s own dav app spreads the signature over four lines with the ): int on the last one, so a grep lists it as if it needed work, while a wrapped signature that really is missing the type looks exactly the same.

So the same regular expression in both steps, reading whole files instead of lines. This one only prints the file names it would touch, it writes nothing:

cd /var/www/nextcloud/apps
find . -path '*/lib/*' -name '*.php' -not -ipath '*/vendor/*' -not -ipath '*/vendor-bin/*' -print0 | xargs -0 -r perl -0777 -ne 'print "$ARGV\n" if /function\s+execute\s*\([^)]*OutputInterface[^)]*\)(?!\s*:)/'

Requiring OutputInterface between the parentheses is what keeps every unrelated execute() out. -0777 reads the file as a whole, so the parameters may be wrapped, named anything or fully qualified, and the brace may sit on the next line. (?!\s*:) skips every signature that already declares a return type, which makes the run repeatable and leaves a wrong one such as : void visible instead of silently mangling it.

The same list, piped into a second stage that does write, patches exactly those files:

find . -path '*/lib/*' -name '*.php' -not -ipath '*/vendor/*' -not -ipath '*/vendor-bin/*' -print0 | xargs -0 -r perl -0777 -ne 'print "$ARGV\0" if /function\s+execute\s*\([^)]*OutputInterface[^)]*\)(?!\s*:)/' | xargs -0 -r perl -0777 -pi.bak -e 's/(function\s+execute\s*\([^)]*OutputInterface[^)]*\))(?!\s*:)/$1: int/g'

Run the first one again afterwards, it should come back empty.

-i.bak keeps the original next to every file it changed, so find . -name '*.php.bak' -delete once the instance is up again. And run it as the web user rather than as root, otherwise the patched files end up root-owned and the next app update cannot write them.

If that holds up, it may be worth having in critical_changes.rst rather than only in this thread.

One thought that goes past this thread. A signature change like this one is machine-detectable, and the data to act on it is public: the store API lists every app that declares compatibility with 35, 167 of them right now, each with its release tarball and an issue tracker URL. So the apps that will break can be found and their maintainers told before the release, instead of one crash report at a time afterwards. Nothing like that seems to exist today. I am happy to run that scan and bring the list if it is of use to anyone.


ernolf