Nextcloud stuck needing DB upgrade after 30 → 32 ("skipped" 31)

Running StartOS with the Nextcloud service. I updated toward 31, it sat in maintenance mode without appearing to progress, so I updated to 32. Now the web UI shows “Update needed / use the command line updater.”

Diagnosis from inside the container:

  • occ status → code version 32.0.11.1, needsDbUpgrade: true, maintenance: false

  • config.php'version' => '30.0.11.1'

So the database is a clean v30 but the package is v32, and occ upgrade correctly refuses the multi-major skip. I have a full pg_dump of the v30 database plus a copy of config.php.

Since the package can’t be downgraded, what’s the supported way to run the intermediate v31 migration on the packaged service? Is a v31 .s9pk available to sideload for this bridge, or is there a package-side migration path?

You can’t (shouldn’t) skip versions. It breaks Nextcloud.

Each version update requires you to update and then run Nextcloud before updating to the next so that its migration scripts can run. We prevent you from “skipping” versions (you can’t update from 30 → 32) but we can’t stop you from arriving in a bad state at 31, then locking in the damage by updating to 32.

There’s no “supported” way to reverse an unsupported upgrade path, but I can turn my notes into a guide for you to adapt. If this fails though, you can just restore your v30 backup and start over.



You don’t need a sideloaded .s9pk. Nextcloud 31.0.13:1 is on the marketplace, and that’s all the bridge you need. A plain downgrade looks blocked only because one file on disk is out of sync — fix that first and the normal downgrade works.

Why it’s stuck

Two version fields drifted apart:

  • /var/www/html/version.php (on disk) = 32.0.11.1 — got overwritten when the 32 image’s entrypoint ran its file copy.
  • config.php 'version' + the database schema = 30.0.11.1 — never advanced, because occ upgrade refused the 30 → 32 (two-major) skip.

The container entrypoint checks version.php before anything else. On the 31 image it sees on-disk 32 > image 31 and aborts with “downgrading is not supported.” That’s almost certainly why the package looked un-downgradeable. Edit version.php back down to 30.0.11.1 and the entrypoint treats 31 as an ordinary one-major upgrade, runs the intermediate migration, and you’re unstuck.

Fix

Run from a root shell inside the Nextcloud container.

0. Snapshot the current (broken) state. You already have the v30 pg_dump + config.php — also copy version.php, and take a fresh StartOS backup so you can return to “broken but recoverable”:

cp /var/www/html/version.php /var/www/html/version.php.bak-32

1. Rewrite version.php to report 30.0.11.1:

cat > /var/www/html/version.php <<'EOF'
<?php
$OC_Version = array(30,0,11,1);
$OC_VersionString = '30.0.11.1';
$OC_Edition = '';
$OC_Channel = 'stable';
$OC_VersionCanBeUpgradedFrom = array (
  'nextcloud' => array (
    '29.0' => true,
    '30.0' => true,
  ),
  'owncloud' => array (
    '10.13' => true,
    '10.14' => true,
    '10.15' => true,
  ),
);
$OC_Build = '';
$vendor = 'nextcloud';
EOF

2. Verify it took (should print 30.0.11.1):

php -r 'require "/var/www/html/version.php"; echo $OC_VersionString, "\n";'

Do not run occ upgrade here — the 32 code is still on disk. Exit and let the package downgrade do the work.

3. Downgrade the package. StartOS UI: Stop the Nextcloud service → Marketplace → Downgrade to 31.0.13:1Start.

4. Watch the logs. You want, in order:

Initializing nextcloud 31.0.13.1 ...
Upgrading nextcloud from 30.0.11.1 ...      # file copy — entrypoint check passed
... Updating database schema ...
... Update successful

Maintenance mode during this is normal. Let it finish — don’t jump to 32 early (that’s what caused the original skip).

If instead you see “downgrading is not supported” or any unexpected version-mismatch, stop and recheck the three numbers below.

5. Confirm 31 is clean:

php /var/www/html/occ status         # expect version: 31.0.13.1, needsDbUpgrade: false

Run these if the upgrade output suggested them:

php /var/www/html/occ db:add-missing-indices
php /var/www/html/occ db:add-missing-columns

6. Now go to 32. Marketplace → Update to 32 → let occ upgrade run the 31 → 32 migration. Verify:

php /var/www/html/occ status         # expect version: 32.x, needsDbUpgrade: false

7. Third-party apps. If any were auto-disabled, check each for a 32-compatible release before re-enabling.

If anything refuses to boot

These three numbers govern the whole state machine — read them before trying anything:

cat /var/www/html/version.php                    # on-disk code version
php /var/www/html/occ config:system:get version  # config/DB version

plus the image version in the entrypoint’s Initializing nextcloud X.X.X.X log line. The entrypoint only proceeds when on-disk ≤ image and the gap is ≤ 1 major; occ upgrade only proceeds when code − config ≤ 1 major.

Thanks, this is what I did:

  • Backed up version.php (the on-disk copy read 32.0.11), then rewrote it to report 30.0.11 and verified with php -r that it parsed and printed 30.0.11.
  • Stopped the service. With version.php at 30, the marketplace did now offer the downgrade to 31.0.13:1 — so your entrypoint-gate theory was right, that’s what had been hiding it.
  • Clicked downgrade to 31.0.13:1.

It failed at the StartOS package migration stage, before the container started:

Install of nextcloud@31.0.13.1 Failed: Migration Failed: Error: Per Nextcloud recommendations, downgrades are prohibited at migration (file:///embassy.js:4305:15) at file:///loadModule.js:240:24 at file:///loadModule.js:242:3

So there’s a second, package-level downgrade guard in embassy.js that’s separate from the Nextcloud entrypoint check — the version.php edit gets past the entrypoint, but not past this. The install rolled back, so the package is back on 32.

Current state: the downgrade rolled back to the 32 package, but I’ve left version.php on disk at 30 for now, so on boot everything comes up (Postgres, nginx) except the Nextcloud frontend, which aborts with Can't start Nextcloud because upgrading from 30.0.11.1 to 32.0.11.1 is not supported.

Is there a way to move forward?

Beyond this point it would be guesswork for me I’m afraid, and things I can’t verify. You may need to restore your v30 backup and proceed through the upgrades without trying to force anything.