We have a rather large setup with thousands of organizations (we're an ISP) and one of the challenges we encounter is adding local admins to each org. We have to do this due to the limitation of some actions that can only be done by such an admin.
We've built some automation (using python) to allow us to quickly add/remove admins to every organization, however we're struggling to find an answer to an annoying issue.
The payload is fine, the script is fine, it works for as many orgs as we can throw at it, we get 200s on most of them. Randomly though, we'll get about 70-80% of the way through and the API Endpoint will start returning 400 Bad Request with a message of:
organizations, createOrganizationAdmin - 400 Bad Request, {'errors': ['Email <omitted> is already registered with a Cisco Meraki Dashboard account. For security purposes, that user must verify their email address before administrator permissions can be granted here.']}
That email does not exist in the org that returned the error, the user has already verified their email, and the weird part, if we run the script again, it works for that failed Org and then starts to fail later on in the list of orgs with the same thing. Sometimes it works flawlessly and we'll mass add the user to over 1000 orgs, other times we may get 50 orgs before it gives the 400 error.
We'd expect a 429 if it was rate-limited, and b/c each iteration of the loop uses the same payload it doesn't seem like the payload itself is bad (confirmed through debugging).
We're not really sure what the cause is here, but figured I'd throw it out into the wind and see if anybody had any thoughts.
Relevant code snippet:
# Imports
import json
import time
import asyncio
import platform
import meraki.aio
import tqdm.asyncio
from InquirerPy import inquirer
< irrelevant code omitted >
# Worker's task, done at each iteration (for each org, using the same args).
try:
response = await aiomeraki.organizations.createOrganizationAdmin(org["id"], admin_email, admin_name, org_access, tags=[])
except meraki.AsyncAPIError as error:
print(f"{org['name']}: {error}")