nextcloud/server · warning · OCSNotFoundException

Bundle not found

Error message

Bundle not found

What it means

OCSNotFoundException (HTTP 404) thrown by ApiController::enableBundle when bundleFetcher->getBundleByIdentifier($bundleId) raises BadMethodCallException, i.e. no app bundle with that identifier is known to the server. Bundles are server-side defined groups of apps (shipped with the appstore data), so the id space depends on the Nextcloud version.

Source

Thrown at apps/appstore/lib/Controller/ApiController.php:290

	/**
	 * Enable all apps of a bundle
	 *
	 * @param string $bundleId - The bundle to enable
	 * @return DataResponse<Http::STATUS_OK, array{}, array{}>
	 * @throws OCSException - if the bundle, or one app within, could not be enabled
	 *
	 * 200: Bundle successfully enabled
	 */
	#[PasswordConfirmationRequired(strict: true)]
	#[ApiRoute(verb: 'POST', url: '/api/v1/bundles/enable')]
	public function enableBundle(string $bundleId): DataResponse {
		try {
			$bundle = $this->bundleFetcher->getBundleByIdentifier($bundleId);
			$this->config->setSystemValue('maintenance', true);
			$this->installer->installAppBundle($bundle);
		} catch (\BadMethodCallException $e) {
			throw new OCSNotFoundException('Bundle not found', $e);
		} catch (\Exception $exception) {
			$this->logger->error('could not enable bundle', ['bundleId' => $bundleId, 'exception' => $exception]);
			throw new OCSException('could not enable bundle', Http::STATUS_INTERNAL_SERVER_ERROR, $exception);
		} finally {
			$this->config->setSystemValue('maintenance', false);
		}

		return new DataResponse([]);
	}

	/**
	 * Convert URL to proxied URL so CSP is no problem
	 */
	private function createProxyPreviewUrl(string $url): string {
		if ($url === '') {
			return '';
		}

View on GitHub (pinned to ecdeb153ff)

Solutions

  1. Refetch the current bundle list from the apps/bundles listing endpoint and use ids from that response
  2. Handle the 404 by refreshing the App Store view instead of retrying the same id
  3. After a server upgrade, reload the settings page so stale bundle ids are discarded
  4. Verify the id casing/format matches exactly
Defensive patterns

Strategy: validation

Validate before calling

// Validate bundleId against the server's current bundle list
const bundles = (await axios.get(generateOcsUrl('/apps/appstore/bundles/list'))).data
if (!bundles.some((b) => b.id === bundleId)) {
	throw new Error(`Unknown bundle: ${bundleId}`)
}
await axios.post(generateOcsUrl('/apps/appstore/bundles/enable'), { bundleId })

Try / catch

try {
	await axios.post(generateOcsUrl('/apps/appstore/bundles/enable'), { bundleId })
} catch (e) {
	if (e?.response?.status === 404) {
		// 'Bundle not found' — refetch the bundle list and re-render
	} else throw e
}

Prevention

When it happens

Trigger: POST /ocs/appstore/bundles/enable with a bundleId that does not exist: id from a cached frontend bundle list of an older Nextcloud version, hand-typed/typo'd id, or an appstore backend that does not provide bundles.

Common situations: Browser tab left open across a server upgrade — the cached bundle list no longer matches; scripts automating bundle enable with hardcoded ids; third-party/custom appstore deployments without bundle metadata.

Related errors


AI-assisted analysis of nextcloud/server@ecdeb153ff (2026-08-17). Data as JSON: /api/errors/25c29675bdad0cc9. Report an issue: GitHub.