{"record":{"id":"d4e47f8efc74ea55","repo":"Budibase/budibase","slug":"unable-to-create-new-user-invitation-invalid","errorCode":null,"errorMessage":"Unable to create new user, invitation invalid.","messagePattern":"Unable to create new user, invitation invalid\\.","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"packages/worker/src/api/controllers/global/users.ts","lineNumber":776,"sourceCode":"          expires: new Date(0),\n        })\n\n        ctx.body = {\n          _id: user._id!,\n          _rev: user._rev!,\n          email: user.email,\n          tenantId: user.tenantId,\n        }\n      }\n    )\n  } catch (err: any) {\n    if (err.code === APIWarningCode.USAGE_LIMIT_EXCEEDED) {\n      // explicitly re-throw limit exceeded errors\n      ctx.throw(400, err?.message || err)\n    }\n    console.warn(\"Error inviting user\", err)\n    ctx.throw(\n      400,\n      err?.message || err || \"Unable to create new user, invitation invalid.\"\n    )\n  }\n}\n\nexport const addUserToWorkspace = async (\n  ctx: UserCtx<\n    EditUserPermissionsResponse,\n    SaveUserResponse,\n    { userId: string; role: string }\n  >\n) => handleUserWorkspacePermission(ctx, ctx.params.userId, ctx.params.role)\n\nexport const removeUserFromWorkspace = async (\n  ctx: UserCtx<\n    EditUserPermissionsResponse,\n    SaveUserResponse,\n    { userId: string }","sourceCodeStart":758,"sourceCodeEnd":794,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/worker/src/api/controllers/global/users.ts#L758-L794","documentation":"The worker's invite-users handler catches errors thrown while creating users/invitations and re-throws them as a 400, preferring the underlying error message and only falling back to 'Unable to create new user, invitation invalid.' if none exists. This generic fallback appears when the failure produced no message at all. It signals the invite or user-creation step failed (duplicate email, quota exceeded re-thrown above this branch, DB error, etc.).","triggerScenarios":"POST to the invite users endpoint where userSdk.invite throws a non-usage-limit error with no message, e.g. invitation cache write fails, payload malformed so err?.message and err are both falsy after handling.","commonSituations":"Bulk CSV import containing rows that all fail validation leaving an empty error; invite storage (CouchDB/Redis) unavailable; tenant user quota checks throwing empty errors; stale client SDKs posting a legacy payload shape.","solutions":["Inspect worker logs for 'Error inviting user' to get the real underlying error object.","Validate the invite payload: emails are valid addresses and rows are not duplicated within the batch.","Retry after confirming the invite cache and CouchDB are healthy.","If a usage limit was actually hit, the endpoint returns the specific USAGE_LIMIT_EXCEEDED message instead — check billing/plan limits separately."],"exampleFix":"// before: posting rows with empty email strings\nawait api.post('/api/global/users/invite', rows)\n// after: filter invalid rows client-side first\nconst valid = rows.filter(r => /^[^@]+@[^@]+\\.[^@]+$/.test(r.email))\nawait api.post('/api/global/users/invite', valid)","handlingStrategy":"validation","validationCode":"const valid = invites.filter(i => /^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(i.email))\nif (valid.length === 0) throw new Error(\"No valid emails to invite\")","typeGuard":"const isInvitable = (u: unknown): u is { email: string } =>\n  typeof u === \"object\" && u !== null && \"email\" in u && typeof (u as { email: unknown }).email === \"string\"","tryCatchPattern":"try {\n  await api.inviteUsers(invites)\n} catch (e) {\n  // prefer e.message; fallback is generic invite failure\n  console.error(e?.message || \"Unable to create new user, invitation invalid.\")\n}","preventionTips":["Validate emails client-side before batching invites","Deduplicate rows in bulk/CSV imports","Check plan usage limits before large invite batches","Verify cache/CouchDB health when invites fail repeatedly"],"tags":["users","invite","worker","api"],"backgroundTag":"user-invite-creation-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}