Environment
- Plane CE v1.3.1 (Docker,
deployments/cli/community/docker-compose.yml, images makeplane/*:v1.3.1)
- Fresh instance, first-run admin bootstrap
Summary
POST /api/instances/admins/sign-up/ returns 500 when is_telemetry_enabled is included as a form value (e.g. is_telemetry_enabled=false). Because the endpoint performs several writes before the failure point, the crash leaves the instance half-configured:
users row created
instance_admins row created
instances.is_setup_done never set (crash before/at instance.save())
Retrying sign-up then redirects with ADMIN_ALREADY_EXIST, while every regular sign-in redirects with INSTANCE_NOT_CONFIGURED — and there is no API/UI way out: InstanceSerializer marks is_setup_done read-only, and no management command sets it. The only recovery is a manual DB UPDATE.
Suspected root cause
In apps/api/plane/license/api/views/admin.py (InstanceAdminSignUpEndpoint.post):
is_telemetry_enabled = request.POST.get("is_telemetry_enabled", True)
...
instance.is_telemetry_enabled = is_telemetry_enabled # raw form STRING, not bool
instance.save()
The raw form string ("false"/"true"/"True") is assigned to a BooleanField and saved; with server-side parameter binding this fails at instance.save() (text parameter into a boolean column). Caveat: the container's plane-error.log stayed empty and no traceback was surfaced, so the pinpoint is from code reading plus DB-state forensics (exact rows present/absent as above) — timing (~160 ms, after two INSERTs) matches.
Note the whole handler also isn't wrapped in a transaction, so any failure at this point strands the instance the same way — wrapping the user/admin/instance writes in transaction.atomic() would make the bootstrap all-or-nothing.
Repro
On a fresh instance:
curl -c jar http://localhost/auth/get-csrf-token/ # take csrf_token
curl -b jar -H "X-CSRFToken: <token>" \
--data-urlencode "email=admin@example.com" \
--data-urlencode "password=<strong password>" \
--data-urlencode "first_name=Admin" \
--data-urlencode "is_telemetry_enabled=false" \
http://localhost/api/instances/admins/sign-up/ # -> 500
Subsequent attempts: ?error_code=5150&error_message=ADMIN_ALREADY_EXIST; sign-in: INSTANCE_NOT_CONFIGURED.
This may also explain #8828 (their error URL echoes is_telemetry_enabled=True as a string, same endpoint, same 500).
Workarounds
- Omit
is_telemetry_enabled from the POST entirely (the Python default True is a real bool), then PATCH /api/instances/ with {"is_telemetry_enabled": false} as the admin.
- If already stranded:
UPDATE instances SET is_setup_done = true; directly in Postgres.
Suggested fix
Coerce the form value (str(value).lower() in {"1", "true"}) before assignment, and wrap the writes in transaction.atomic().
Environment
deployments/cli/community/docker-compose.yml, imagesmakeplane/*:v1.3.1)Summary
POST /api/instances/admins/sign-up/returns 500 whenis_telemetry_enabledis included as a form value (e.g.is_telemetry_enabled=false). Because the endpoint performs several writes before the failure point, the crash leaves the instance half-configured:usersrow createdinstance_adminsrow createdinstances.is_setup_donenever set (crash before/atinstance.save())Retrying sign-up then redirects with
ADMIN_ALREADY_EXIST, while every regular sign-in redirects withINSTANCE_NOT_CONFIGURED— and there is no API/UI way out:InstanceSerializermarksis_setup_doneread-only, and no management command sets it. The only recovery is a manual DBUPDATE.Suspected root cause
In
apps/api/plane/license/api/views/admin.py(InstanceAdminSignUpEndpoint.post):The raw form string (
"false"/"true"/"True") is assigned to aBooleanFieldand saved; with server-side parameter binding this fails atinstance.save()(text parameter into a boolean column). Caveat: the container'splane-error.logstayed empty and no traceback was surfaced, so the pinpoint is from code reading plus DB-state forensics (exact rows present/absent as above) — timing (~160 ms, after twoINSERTs) matches.Note the whole handler also isn't wrapped in a transaction, so any failure at this point strands the instance the same way — wrapping the user/admin/instance writes in
transaction.atomic()would make the bootstrap all-or-nothing.Repro
On a fresh instance:
Subsequent attempts:
?error_code=5150&error_message=ADMIN_ALREADY_EXIST; sign-in:INSTANCE_NOT_CONFIGURED.This may also explain #8828 (their error URL echoes
is_telemetry_enabled=Trueas a string, same endpoint, same 500).Workarounds
is_telemetry_enabledfrom the POST entirely (the Python defaultTrueis a real bool), thenPATCH /api/instances/with{"is_telemetry_enabled": false}as the admin.UPDATE instances SET is_setup_done = true;directly in Postgres.Suggested fix
Coerce the form value (
str(value).lower() in {"1", "true"}) before assignment, and wrap the writes intransaction.atomic().