Skip to content

[Bug]: appsallowlist silently strands enabled apps as "incompatible" during major upgrades — updater's post-disable re-fetch is gated by the allowlist #62086

Description

@moodyjmz

⚠️ This issue respects the following points ⚠️

  • This is a bug — server behaviour (silent gate + misleading error + no retry + no pre-flight), not a configuration/webserver/proxy issue. Setting appsallowlist is legitimate; the bug is how the updater fails against it.
  • Not already reported (searched GitHub + forum; appsallowlist returns zero related issues).
  • Server is up to date (observed on 33.0.5; mechanism unchanged since 23.0.0).
  • I agree to follow the Code of Conduct.

TL;DR

If you set appsallowlist in config.php and have a valid subscription, a major upgrade can permanently disable enabled apps that aren't on the list — showing "not compatible with this version of the server" even though a compatible release exists in the App Store.

Why: on a major upgrade the server disables each app that doesn't yet declare support for the new version, then tries to re-fetch a compatible release and re-enable it. That re-fetch is filtered by appsallowlist. Apps not on the list are silently blocked, left disabled on their old version, and reported as "incompatible" — the wrong cause.

It looks random across a fleet but isn't: instances differ only because their allowlist contents or enabled-app sets differ. Fixing apps one-at-a-time as they break leaves every other unlisted app exposed to the next major upgrade. The workaround (add every enabled app to the allowlist) works but is reactive and undocumented.

Ask: don't gate the updater's own re-enable of an already-installed app on appsallowlist; failing that, report the real cause and warn before the upgrade runs.


Bug description

During a major-version upgrade, Updater disables each enabled app whose installed version's max-version doesn't cover the new major, then immediately tries to re-fetch a compatible release from the App Store and re-enable it (Updater::upgradeAppStoreApps()). That re-fetch goes through the App Store fetch pathway, which is filtered by appsallowlist.

If an enabled app is not in appsallowlist, the re-fetch is silently blocked, the wrapping code catches the exception and logs a generic error, and the app is left permanently disabled on its old version. The UI/occ then reports "not compatible with this version of the server" — misattributing the cause: the app has a compatible release published, it just isn't allowed through the gate.

What makes this hard to diagnose:

  • appsallowlist is inert in normal operation. An enabled app on a compatible version never touches the gated pathway, so an allowlist set once (for governance) sits harmless for years and only bites the first time a major upgrade needs to re-fetch an unlisted app.
  • Subscription-gated. The filter only applies when delegateHasValidSubscription() is true, so it's effectively invisible on community installs and specifically hits subscription-managed / enterprise fleets.
  • Single attempt, no retry, no distinguishing error. "Blocked by allowlist", "genuine incompatibility", and "network failure" all surface identically.
  • Looks random across a fleet but is deterministic given each instance's config.

Source references

Enforcement — lib/private/App/AppStore/Fetcher/AppFetcher.php (current master, ~lines 163-168):

$allowList = $this->config->getSystemValue('appsallowlist');
if (is_array($allowList) && $this->registry->delegateHasValidSubscription()) {
    return array_values(array_filter($apps, function (array $app) use ($allowList) {
        return in_array($app['id'], $allowList);
    }));
}
  • This is the only place in the codebase enforcing appsallowlist.
  • Introduced in commit 1a6bac58 ("Allow to whitelist apps from the apsptore", authored 2021-10-08), first released in NC 23.0.0. The subscription gate was part of the same commit, and the logic is unchanged since — this is not a version-specific regression, it's just first noticed at whichever major upgrade happens to need a re-fetch.
  • Trigger path: Updater::upgradeAppStoreApps()Installer::isUpdateAvailable() / updateAppstoreApp() → App Store fetch (gated). The wrapping catch (\Exception $ex) { $this->log->error(...) } swallows the allowlist block into a generic log line.

Steps to reproduce

  1. Instance with a valid subscription.
  2. Set appsallowlist in config.php to a list that omits at least one currently-enabled App Store app (e.g. deck, spreed, notes, notify_push, files_antivirus, collectives).
  3. Perform a major-version upgrade where that app's installed version's max-version predates the new major (so the updater must re-fetch).
  4. Observe: the omitted app is disabled and cannot be re-enabled/updated; UI reports "not compatible with this version of the server" despite a compatible release existing in the store.

Expected behavior

Either:

  • the updater's own post-disable re-fetch should not be gated by appsallowlist (that setting is meant to restrict admin-initiated store installs, not the server re-enabling an app it already has installed); or
  • if it must be gated, the failure must be reported honestly ("blocked by appsallowlist", not "incompatible") and surfaced before the upgrade proceeds.

Actual: app silently stranded disabled on its old version, misleading "incompatible" error, no retry, no pre-warning.

Nextcloud Server version

33.0.5 (observed). Mechanism present on every version ≥ 23.0.0.

Configuration / environment

  • appsallowlist set in config.php; instance holds a valid subscription (both required to trigger).
  • Deployed via Helm chart (Kubernetes), but the mechanism is deployment-independent.

Proposed fixes (priority order)

  1. Don't gate the updater's post-disable re-fetch on appsallowlist, or treat "already installed + enabled before the upgrade" as implicitly allowed. Closes the root cause. (Worth confirming the original design intent of 1a6bac58 with its author — the setting reads as "restrict what admins can install from the store", and it's unclear it was ever meant to gate the updater re-enabling something already present.)
  2. Distinguish the error. When a fetch is blocked by appsallowlist, say so in the log, in occ, and in the upgrade UI — rather than the generic "not compatible" message. (Overlaps with [Bug]: Incorrect incompatible apps notification during Nextcloud server update from version 32.0.9 to version 33.0.3 #60477 and Upgrade experience: confusing message about disabled incompatible apps #21066.)
  3. Pre-upgrade pre-flight check. A native occ check listing enabled apps not on appsallowlist (and enabled apps with no compatible release) before the upgrade starts. (Revives the intent of check for app compatibility at start of occ upgrade, so upgrade doesn't disable apps #35001, closed as not-planned but exactly this class of safeguard.)
  4. Retry / don't silent-catch. The single-attempt + silent-catch + no-retry pattern in upgradeAppStoreApps() is a weakness independent of the allowlist, worth hardening in the same pass.

Impact

Subscription-managed fleets using appsallowlist for governance can have Nextcloud-maintained App Store apps (Deck, Talk, Notes, the fulltextsearch family, notify_push, files_antivirus, collectives, …) silently and permanently disabled by a routine major upgrade, with an error that points diagnosis at the wrong cause. The only workaround today is reactive per-app allowlisting; no proactive warning exists.

Related

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    To triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions