{"record":{"id":"8037fe84fb73ffa7","repo":"nextcloud/server","slug":"could-not-update-app","errorCode":null,"errorMessage":"could not update app","messagePattern":"could not update app","errorType":"http","errorClass":"OCSException","httpStatus":500,"severity":"error","filePath":"apps/appstore/lib/Controller/ApiController.php","lineNumber":267,"sourceCode":"\t * @throws OCSException - if the app could not be updated\n\t *\n\t * 200: App successfully updated\n\t */\n\t#[PasswordConfirmationRequired(strict: true)]\n\t#[ApiRoute(verb: 'POST', url: '/api/v1/apps/update')]\n\tpublic function updateApp(string $appId): DataResponse {\n\t\t$appId = $this->appManager->cleanAppId($appId);\n\n\t\t$this->config->setSystemValue('maintenance', true);\n\t\ttry {\n\t\t\t$result = $this->installer->updateAppstoreApp($appId);\n\t\t\t$this->config->setSystemValue('maintenance', false);\n\t\t\tif ($result === false) {\n\t\t\t\tthrow new \\Exception('Update failed');\n\t\t\t}\n\t\t} catch (\\Exception $exception) {\n\t\t\t$this->config->setSystemValue('maintenance', false);\n\t\t\tthrow new OCSException('could not update app', Http::STATUS_INTERNAL_SERVER_ERROR, $exception);\n\t\t}\n\n\t\treturn new DataResponse([]);\n\t}\n\n\t/**\n\t * Enable all apps of a bundle\n\t *\n\t * @param string $bundleId - The bundle to enable\n\t * @return DataResponse<Http::STATUS_OK, array{}, array{}>\n\t * @throws OCSException - if the bundle, or one app within, could not be enabled\n\t *\n\t * 200: Bundle successfully enabled\n\t */\n\t#[PasswordConfirmationRequired(strict: true)]\n\t#[ApiRoute(verb: 'POST', url: '/api/v1/bundles/enable')]\n\tpublic function enableBundle(string $bundleId): DataResponse {\n\t\ttry {","sourceCodeStart":249,"sourceCodeEnd":285,"githubUrl":"https://github.com/nextcloud/server/blob/ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3/apps/appstore/lib/Controller/ApiController.php#L249-L285","documentation":"OCSException (HTTP 500) thrown by ApiController::updateApp when installer->updateAppstoreApp() returns false or throws. The controller sets maintenance mode to true before the update and back to false afterwards (including in catch), so the store app is replaced atomically; the wrapped \\Exception is chained into the OCS error.","triggerScenarios":"POST /ocs/appstore/apps/update failing because no update is actually available for the current server version, the download from the app store failed, extraction/permission errors under apps/, or a mid-update database exception.","commonSituations":"Server without outbound access to the app store; apps/ not writable; app store not yet serving a compatible release for the installed Nextcloud version; concurrent update attempts; instance left in maintenance mode after a fatal (not caught) failure.","solutions":["Confirm an update exists for the app at your Nextcloud version in the Apps page before calling update","Check nextcloud.log for the chained exception and apps/ writability","If the server is stuck in maintenance mode afterwards, run `occ maintenance:mode --off`","Retry via `occ app:update <appId>` to see CLI-level errors"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n\tawait axios.post(generateOcsUrl('/apps/appstore/apps/update'), { appId })\n} catch (e) {\n\t// 500 'could not update app' — chained exception in nextcloud.log\n\t// afterwards confirm maintenance mode was cleared: occ maintenance:mode --off\n}","preventionTips":["Only offer Update when the app listing actually reports a newer version for your NC release","Keep apps/ writable and appstore reachable before starting updates","After any failed update, verify the maintenance flag is off before users report lockouts"],"tags":["appstore","apps","update","maintenance-mode","php"],"backgroundTag":"app-update-failed","analyzedSha":"ecdeb153ffdf227235c9a7e2d13dbe0f9c817bc3","analyzedAt":"2026-08-17T01:36:13.386Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}