App store responding by a "429 Too many requests"

The Basics

  • Nextcloud Server version (e.g., 29.x.x):
    • 29.0.11
  • Operating system and version (e.g., Ubuntu 24.04):
    • Debian 12 up to date
  • Web server and version (e.g, Apache 2.4.25):
    • Apache 2.4.62
  • PHP version (e.g, 8.3):
    • 8.2.26
  • Is this the first time you’ve seen this error? (Yes / No):
    • No
  • When did this problem seem to first start?
    • about 10 days
  • Installation method (e.g. AlO, NCP, Bare Metal/Archive, etc.)
    • From archive
  • Are you using CloudfIare, mod_security, or similar? (Yes / No)
    • No

Summary of the issue you are facing:

I have a dozen of Nextccloud installed on a server for personnal/family projects, and trying to update app, via occ or in the browser is impossible : the app store responds with a “429 Too many requests” answer.

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

I use a script which goes through each Nextcloud installed and runs :

sudo -u www-data php occ app:update --all

Since 2 years, it was working fine, but since a dozen of days, first nextcloud has its apps updated, but next ones are getting a 429 response from app store.

I’ve tried to add a delay of 10s between each update, but same 429.

Is there an ideal time between requests to avoid ban ?
Is there anything changed recently in store web server config ?

Log entries

Nextcloud

"Exception": "GuzzleHttp\\Exception\\ClientException",
    "Message": "Client error: `GET https://apps.nextcloud.com/api/v1/apps.json` resulted in a `429 Too Many Requests` response:\n<html>\r\n<head><title>429 Too Many Requests</title></head>\r\n<body>\r\n<center><h1>429 Too Many Requests</h1></center>\r\n<hr> (truncated...)\n",
    "Code": 429,

Configuration

Nextcloud

The output of occ config:list system or similar is best, but, if not possible, the contents of your config.php file from /path/to/nextcloud is fine (make sure to remove any identifiable information!):

{
    "system": {
        "passwordsalt": "***REMOVED SENSITIVE VALUE***",
        "secret": "***REMOVED SENSITIVE VALUE***",
        "trusted_domains": [
            "nuage.fracama.org"
        ],
        "datadirectory": "***REMOVED SENSITIVE VALUE***",
        "dbtype": "mysql",
        "version": "29.0.11.1",
        "overwrite.cli.url": "http:\/\/localhost",
        "dbname": "***REMOVED SENSITIVE VALUE***",
        "dbhost": "***REMOVED SENSITIVE VALUE***",
        "dbport": "",
        "dbtableprefix": "oc_",
        "mysql.utf8mb4": true,
        "dbuser": "***REMOVED SENSITIVE VALUE***",
        "dbpassword": "***REMOVED SENSITIVE VALUE***",
        "installed": true,
        "instanceid": "***REMOVED SENSITIVE VALUE***",
        "logtimezone": "UTC",
        "default_language": "fr",
        "default_phone_region": "FR",
        "defaultapp": "files",
        "skeletondirectory": "",
        "knowledgebaseenabled": false,
        "enable_avatars": true,
        "enable_previews": true,
        "preview_max_x": 1200,
        "preview_max_y": 800,
        "auth.bruteforce.protection.enabled": true,
        "memcache.local": "\\OC\\Memcache\\APCu",
        "memcache.locking": "\\OC\\Memcache\\Redis",
        "memcache.distributed": "\\OC\\Memcache\\Redis",
        "redis": {
            "host": "***REMOVED SENSITIVE VALUE***",
            "port": 6382,
            "password": "***REMOVED SENSITIVE VALUE***",
            "timeout": 1.5,
            "read_timeout": 1.5
        },
        "mail_domain": "***REMOVED SENSITIVE VALUE***",
        "mail_from_address": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpauth": true,
        "mail_smtpauthtype": "LOGIN",
        "mail_smtpmode": "smtp",
        "mail_smtpname": "***REMOVED SENSITIVE VALUE***",
        "mail_smtppassword": "***REMOVED SENSITIVE VALUE***",
        "mail_smtphost": "***REMOVED SENSITIVE VALUE***",
        "mail_smtpport": 465,
        "mail_smtpsecure": "ssl",
        "mail_sendmailmode": "smtp",
        "maintenance_window_start": 1,
        "maintenance": false,
        "filesystem_check_changes": 1,
        "loglevel": 3,
        "updater.release.channel": "stable",
        "theme": "",
        "upgrade.disable-web": true
    }
}

Apps

The output of occ app:list (if possible).

Enabled:
  - bruteforcesettings: 2.9.0
  - calendar: 4.7.16
  - circles: 29.0.0-dev
  - cloud_federation_api: 1.12.0
  - contacts: 6.0.2
  - dashboard: 7.9.0
  - dav: 1.30.1
  - deck: 1.13.3
  - external: 5.4.1
  - federatedfilesharing: 1.19.0
  - files: 2.1.1
  - files_downloadlimit: 2.0.0
  - files_pdfviewer: 2.10.0
  - files_reminders: 1.2.0
  - files_sharing: 1.21.0
  - files_trashbin: 1.19.0
  - forms: 4.3.5
  - logreader: 2.14.0
  - lookup_server_connector: 1.17.0
  - notifications: 2.17.0
  - oauth2: 1.17.1
  - password_policy: 1.19.0
  - photos: 2.5.0
  - privacy: 1.13.0
  - provisioning_api: 1.19.0
  - recommendations: 2.1.0
  - related_resources: 1.4.0
  - richdocuments: 8.4.9
  - serverinfo: 1.19.0
  - settings: 1.12.0
  - tasks: 0.16.1
  - text: 3.10.1
  - theming: 2.4.0
  - twofactor_backupcodes: 1.18.0
  - updatenotification: 1.19.1
  - viewer: 2.3.0
  - weather_status: 1.9.0
  - workflowengine: 2.11.0
Disabled:
  - activity: 2.21.1 (installed 2.17.0)
  - admin_audit: 1.19.0
  - comments: 1.19.0 (installed 1.15.0)
  - contactsinteraction: 1.10.0 (installed 1.6.0)
  - encryption: 2.17.0
  - federation: 1.19.0 (installed 1.15.0)
  - files_external: 1.21.0
  - files_versions: 1.22.0 (installed 1.18.0)
  - firstrunwizard: 2.18.0 (installed 2.14.0)
  - nextcloud_announcements: 1.18.0 (installed 1.14.0)
  - sharebymail: 1.19.0 (installed 1.15.0)
  - support: 1.12.0 (installed 1.8.0)
  - survey_client: 1.17.0 (installed 1.13.0)
  - suspicious_login: 7.0.0
  - systemtags: 1.19.0 (installed 1.15.0)
  - twofactor_totp: 11.0.0-dev
  - user_ldap: 1.20.0
  - user_status: 1.9.0 (installed 1.5.0)

Hey, was there another change in that timeframe on your side? The app store config hasn’t been touched for a few month now.

Thx @SysKeeper for your interest.
I did not change anything since last update to 29.0.11.
My script for updating my NXC is running every night for months.
It just get 429 responses since a dozen of days.

By the way, the ban from app store is short, and I managed to add 30s delay between each update request, and this time it passed :+1:

Still, there is a mystery here :slight_smile:

I think there are to many requests for your Nextcloud instance. Maybe a cronjob problem, a Nextcloud problem, an app problem, …

Maybe you can stop your webserver (Nextcloud) and/or cron for a while. Maybe you can uninstall some apps you do not really need for a while.

Really interesting, I am not aware of a change from our side. If you like, you can drop me your external IP and I can check the logs.

@SysKeeper : can’t find a private message feature here, how can I send you the IP of my server privately ?

@devnull : I’ve checked that before, there is no flood from my server, no exotic app, no check for update other that the one the cron does (now 1 time a week)

Is there a solution for this? I’m getting the same http error.

There’s no need for a general solution, if end up in this case, there were too many requests to the app store.

Are you querying the serverinfo API by chance?

We had the same problem when upgrading from 30.0.10 to 31.0.5. Is the rate limit per IP or IP range? We have several Nextcloud installations on one server, max 10. Each server has its own IP address. We make sure that we only update one Nextcloud at a time per server.

source ip in this case:

  • 185.169.84.224
  • 2a04:503:0:1022::224
Log
{
  "reqId": "7H3ChwhOP2YhbAfyP30d",
  "level": 2,
  "time": "2025-05-19T22:22:14+00:00",
  "remoteAddr": "",
  "user": "--",
  "app": "appstoreFetcher",
  "method": "",
  "url": "--",
  "message": "Client error: `GET https://apps.nextcloud.com/api/v1/apps.json` resulted in a `429 Too Many Requests` response:\n<html>\r\n<head><title>429 Too Many Requests</title></head>\r\n<body>\r\n<center><h1>429 Too Many Requests</h1></center>\r\n<hr> (truncated...)\n",
  "userAgent": "--",
  "version": "31.0.5.1",
  "exception": {
    "Exception": "GuzzleHttp\\Exception\\ClientException",
    "Message": "Client error: `GET https://apps.nextcloud.com/api/v1/apps.json` resulted in a `429 Too Many Requests` response:\n<html>\r\n<head><title>429 Too Many Requests</title></head>\r\n<body>\r\n<center><h1>429 Too Many Requests</h1></center>\r\n<hr> (truncated...)\n",
    "Code": 429,
    "Trace": [
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/guzzle/src/Middleware.php",
        "line": 72,
        "function": "create",
        "class": "GuzzleHttp\\Exception\\RequestException",
        "type": "::",
        "args": [
          "*** sensitive parameters replaced ***"
        ]
      },
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/promises/src/Promise.php",
        "line": 209,
        "function": "GuzzleHttp\\{closure}",
        "class": "GuzzleHttp\\Middleware",
        "type": "::",
        "args": [
          "*** sensitive parameters replaced ***"
        ]
      },
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/promises/src/Promise.php",
        "line": 158,
        "function": "callHandler",
        "class": "GuzzleHttp\\Promise\\Promise",
        "type": "::",
        "args": [
          1,
          "*** sensitive parameters replaced ***",
          "*** sensitive parameters replaced ***"
        ]
      },
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/promises/src/TaskQueue.php",
        "line": 52,
        "function": "GuzzleHttp\\Promise\\{closure}",
        "class": "GuzzleHttp\\Promise\\Promise",
        "type": "::",
        "args": [
          "*** sensitive parameters replaced ***"
        ]
      },
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/promises/src/Promise.php",
        "line": 251,
        "function": "run",
        "class": "GuzzleHttp\\Promise\\TaskQueue",
        "type": "->",
        "args": [
          true
        ]
      },
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/promises/src/Promise.php",
        "line": 227,
        "function": "invokeWaitFn",
        "class": "GuzzleHttp\\Promise\\Promise",
        "type": "->",
        "args": []
      },
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/promises/src/Promise.php",
        "line": 272,
        "function": "waitIfPending",
        "class": "GuzzleHttp\\Promise\\Promise",
        "type": "->",
        "args": []
      },
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/promises/src/Promise.php",
        "line": 229,
        "function": "invokeWaitList",
        "class": "GuzzleHttp\\Promise\\Promise",
        "type": "->",
        "args": []
      },
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/promises/src/Promise.php",
        "line": 69,
        "function": "waitIfPending",
        "class": "GuzzleHttp\\Promise\\Promise",
        "type": "->",
        "args": []
      },
      {
        "file": "/home/nextcloud/www/3rdparty/guzzlehttp/guzzle/src/Client.php",
        "line": 189,
        "function": "wait",
        "class": "GuzzleHttp\\Promise\\Promise",
        "type": "->",
        "args": []
      },
      {
        "file": "/home/nextcloud/www/lib/private/Http/Client/Client.php",
        "line": 206,
        "function": "request",
        "class": "GuzzleHttp\\Client",
        "type": "->",
        "args": [
          "get",
          "*** sensitive parameters replaced ***",
          {
            "verify": "/home/nextcloud/www/resources/config/ca-bundle.crt",
            "timeout": 60,
            "allow_redirects": {
              "on_redirect": {
                "__class__": "Closure"
              }
            },
            "nextcloud": {
              "allow_local_address": false
            },
            "headers": {
              "User-Agent": "Nextcloud Server Crawler",
              "Accept-Encoding": "gzip"
            },
            "0": "And 1 more entries, set log level to debug to see all entries"
          }
        ]
      },
      {
        "file": "/home/nextcloud/www/lib/private/App/AppStore/Fetcher/Fetcher.php",
        "line": 89,
        "function": "get",
        "class": "OC\\Http\\Client\\Client",
        "type": "->",
        "args": [
          "*** sensitive parameters replaced ***"
        ]
      },
      {
        "file": "/home/nextcloud/www/lib/private/App/AppStore/Fetcher/AppFetcher.php",
        "line": 55,
        "function": "fetch",
        "class": "OC\\App\\AppStore\\Fetcher\\Fetcher",
        "type": "->",
        "args": [
          "",
          ""
        ]
      },
      {
        "file": "/home/nextcloud/www/lib/private/App/AppStore/Fetcher/Fetcher.php",
        "line": 167,
        "function": "fetch",
        "class": "OC\\App\\AppStore\\Fetcher\\AppFetcher",
        "type": "->",
        "args": [
          "",
          "",
          false
        ]
      },
      {
        "file": "/home/nextcloud/www/lib/private/App/AppStore/Fetcher/AppFetcher.php",
        "line": 156,
        "function": "get",
        "class": "OC\\App\\AppStore\\Fetcher\\Fetcher",
        "type": "->",
        "args": [
          false
        ]
      },
      {
        "file": "/home/nextcloud/www/lib/private/Installer.php",
        "line": 381,
        "function": "get",
        "class": "OC\\App\\AppStore\\Fetcher\\AppFetcher",
        "type": "->",
        "args": [
          false
        ]
      },
      {
        "file": "/home/nextcloud/www/core/Command/App/Update.php",
        "line": 80,
        "function": "isUpdateAvailable",
        "class": "OC\\Installer",
        "type": "->",
        "args": [
          "comments",
          false
        ]
      },
      {
        "file": "/home/nextcloud/www/3rdparty/symfony/console/Command/Command.php",
        "line": 326,
        "function": "execute",
        "class": "OC\\Core\\Command\\App\\Update",
        "type": "->",
        "args": [
          {
            "__class__": "Symfony\\Component\\Console\\Input\\ArgvInput"
          },
          {
            "__class__": "Symfony\\Component\\Console\\Output\\ConsoleOutput"
          }
        ]
      },
      {
        "file": "/home/nextcloud/www/3rdparty/symfony/console/Application.php",
        "line": 1078,
        "function": "run",
        "class": "Symfony\\Component\\Console\\Command\\Command",
        "type": "->",
        "args": [
          {
            "__class__": "Symfony\\Component\\Console\\Input\\ArgvInput"
          },
          {
            "__class__": "Symfony\\Component\\Console\\Output\\ConsoleOutput"
          }
        ]
      },
      {
        "file": "/home/nextcloud/www/3rdparty/symfony/console/Application.php",
        "line": 324,
        "function": "doRunCommand",
        "class": "Symfony\\Component\\Console\\Application",
        "type": "->",
        "args": [
          {
            "__class__": "OC\\Core\\Command\\App\\Update"
          },
          {
            "__class__": "Symfony\\Component\\Console\\Input\\ArgvInput"
          },
          {
            "__class__": "Symfony\\Component\\Console\\Output\\ConsoleOutput"
          }
        ]
      },
      {
        "file": "/home/nextcloud/www/3rdparty/symfony/console/Application.php",
        "line": 175,
        "function": "doRun",
        "class": "Symfony\\Component\\Console\\Application",
        "type": "->",
        "args": [
          {
            "__class__": "Symfony\\Component\\Console\\Input\\ArgvInput"
          },
          {
            "__class__": "Symfony\\Component\\Console\\Output\\ConsoleOutput"
          }
        ]
      },
      {
        "file": "/home/nextcloud/www/lib/private/Console/Application.php",
        "line": 187,
        "function": "run",
        "class": "Symfony\\Component\\Console\\Application",
        "type": "->",
        "args": [
          {
            "__class__": "Symfony\\Component\\Console\\Input\\ArgvInput"
          },
          {
            "__class__": "Symfony\\Component\\Console\\Output\\ConsoleOutput"
          }
        ]
      },
      {
        "file": "/home/nextcloud/www/console.php",
        "line": 87,
        "function": "run",
        "class": "OC\\Console\\Application",
        "type": "->",
        "args": [
          {
            "__class__": "Symfony\\Component\\Console\\Input\\ArgvInput"
          }
        ]
      },
      {
        "file": "/home/nextcloud/www/occ",
        "line": 33,
        "args": [
          "/home/nextcloud/www/console.php"
        ],
        "function": "require_once"
      }
    ],
    "File": "/home/nextcloud/www/3rdparty/guzzlehttp/guzzle/src/Exception/RequestException.php",
    "Line": 111,
    "message": "Client error: `GET https://apps.nextcloud.com/api/v1/apps.json` resulted in a `429 Too Many Requests` response:\n<html>\r\n<head><title>429 Too Many Requests</title></head>\r\n<body>\r\n<center><h1>429 Too Many Requests</h1></center>\r\n<hr> (truncated...)\n",
    "exception": {},
    "CustomMessage": "Client error: `GET https://apps.nextcloud.com/api/v1/apps.json` resulted in a `429 Too Many Requests` response:\n<html>\r\n<head><title>429 Too Many Requests</title></head>\r\n<body>\r\n<center><h1>429 Too Many Requests</h1></center>\r\n<hr> (truncated...)\n"
  }
}

The sequence of our update script is roughly:

  1. update nextcloud from zip archive
  2. occ upgrade --no-interaction
  3. occ app:update --all --no-interaction
  4. re-enable apps that were previously enabled

We already use a local mirror for the ZIP archive because we do not want to overload the download server. We do not use a mirror for the App Store. Also interesting: Our update script should log if occ upgrade --no-interaction fails. But this did not happen. Which brings me to the question whether occ return an error code at a rate limit or not?

Should be by IP. I took a quick look at the last days of the source ips you mentioned, there were requests, but non ran into an issue.

Strange. Thanks for checking though, I’ll do a follow up in this thread if it happens again*.


*and the thread is still open…