makeplane/plane · warning · CommandError

The provided email is already an instance admin.

Error message

The provided email is already an instance admin.

What it means

Raised when `InstanceAdmin.objects.get_or_create(user=user, instance=instance, role=20)` returns `created=False` (lines 35-38), i.e. an `InstanceAdmin` row for that user already exists. IMPORTANT: this raise occurs inside the `try` block (line 30) whose `except Exception` (lines 41-43) catches it, prints it, and re-raises the GENERIC message 'Failed to create the instance admin.' (error 84). So the operator normally never sees this message — they see [84] instead. This masking is a latent bug.

Source

Thrown at apps/api/plane/db/management/commands/create_instance_admin.py:38

    def handle(self, *args, **options):
        admin_email = options.get("admin_email", False)

        if not admin_email:
            raise CommandError("Please provide the email of the admin.")

        user = User.objects.filter(email=admin_email).first()
        if user is None:
            raise CommandError("User with the provided email does not exist.")

        try:
            # Get the instance
            instance = Instance.objects.last()

            # Get or create an instance admin
            _, created = InstanceAdmin.objects.get_or_create(user=user, instance=instance, role=20)

            if not created:
                raise CommandError("The provided email is already an instance admin.")

            self.stdout.write(self.style.SUCCESS("Successfully created the admin"))
        except Exception as e:
            print(e)
            raise CommandError("Failed to create the instance admin.")

View on GitHub (pinned to 1c8a60f858)

Solutions

  1. Recognize the user is already an admin — no action needed; this is not a real failure.
  2. To list existing admins: `python manage.py shell -c "from plane.license.models import InstanceAdmin; print([a.user.email for a in InstanceAdmin.objects.all()])"`
  3. Fix the masking bug by moving the `if not created` check outside the try, or by catching only specific DB exceptions instead of bare `Exception`.

Example fix

# before (bug: [83] is swallowed and re-raised as [84])
try:
    _, created = InstanceAdmin.objects.get_or_create(...)
    if not created:
        raise CommandError("The provided email is already an instance admin.")
except Exception as e:
    print(e)
    raise CommandError("Failed to create the instance admin.")
# after (move the idempotency check out of the try)
_, created = InstanceAdmin.objects.get_or_create(user=user, instance=instance, role=20)
if not created:
    self.stdout.write(self.style.WARNING("Already an instance admin"))
    return
Defensive patterns

Strategy: try-catch

Validate before calling

from plane.license.models import InstanceAdmin
from plane.db.models import User
already = InstanceAdmin.objects.filter(user__email='admin@example.com').exists()
# if already: skip the command; it is idempotent-but-noisy

Type guard

def is_already_instance_admin(email: str) -> bool:
    from plane.license.models import InstanceAdmin
    return InstanceAdmin.objects.filter(user__email=email).exists()

Try / catch

# WARNING: create_instance_admin masks [83] as [84] via its bare except.
# Pre-check instead of relying on the message:
from plane.license.models import InstanceAdmin
if InstanceAdmin.objects.filter(user__email=email).exists():
    print('already an admin; skipping')
else:
    call_command('create_instance_admin', email)

Prevention

When it happens

Trigger: Running `create_instance_admin` for a user who is already an instance admin; the get_or_create finds the existing row and `created` is False.

Common situations: Re-running the command after a previous successful run; an admin was provisioned via setup scripts or the UI already.

Related errors


AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12). Data as JSON: /api/errors/395e68a1f32db869. Report an issue: GitHub.