{"record":{"id":"d72ec897109c9f4f","repo":"appsmithorg/appsmith","slug":"error","errorCode":null,"errorMessage":"error","messagePattern":"error","errorType":"validation","errorClass":"SubmissionError","httpStatus":null,"severity":"error","filePath":"app/client/src/ce/pages/workspace/helpers.ts","lineNumber":85,"sourceCode":"  dispatch: any, // TODO: Fix this the next time the file is edited\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): Promise<any> => {\n  const data = values.usersByRole.map((value) => ({\n    permissionGroupId: value.permissionGroupId,\n    emails: value.users ? value.users.split(\",\") : [],\n  }));\n\n  return new Promise((resolve, reject) => {\n    dispatch({\n      type: ReduxActionTypes.INVITE_USERS_TO_WORKSPACE_INIT,\n      payload: {\n        resolve,\n        reject,\n        data,\n      },\n    });\n  }).catch((error) => {\n    throw new SubmissionError(error);\n  });\n};\n\nexport const inviteUsersToWorkspace = async (\n  // TODO: Fix this the next time the file is edited\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  values: any,\n  // TODO: Fix this the next time the file is edited\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  dispatch: any,\n  // TODO: Fix this the next time the file is edited\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): Promise<any> => {\n  const data = {\n    permissionGroupId: values.permissionGroupId,\n    usernames: values.users ? values.users.split(\",\") : [],\n    workspaceId: values.workspaceId,\n    ...(\"recaptchaToken\" in values && {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/appsmithorg/appsmith/blob/8cd9021c24cdbea1c3c12c966073708e83db60c2/app/client/src/ce/pages/workspace/helpers.ts#L67-L103","documentation":"Thrown in inviteUsersToWorkspaceSubmitHandler(). It dispatches INVITE_USERS_TO_WORKSPACE_INIT with resolve/reject tied to a Promise; if the saga rejects (e.g. server-side validation of emails/roles), the .catch wraps the payload in redux-form's SubmissionError. The literal message 'error' is just the default fallback; the real user-facing messages come from the rejected payload object (typically {usersByRole, _error}) which redux-form maps onto form fields. SubmissionError is redux-form's signal that submission failed with field-level errors rather than an unexpected throw.","triggerScenarios":"Submitting the invite-users-to-workspace form and having the backend reject it: invalid email syntax, unknown role/permissionGroupId, duplicate invitations, or rate limiting. The saga calls reject(errorPayload), the catch re-throws as SubmissionError so redux-form renders the per-field errors.","commonSituations":"Typo in an invited email; selecting a role the current user cannot grant; inviting an already-member email; backend returns a generic {error:'...'} that does not map to a form field, surfacing as a generic form error.","solutions":["Validate emails client-side before submit so common typos never reach the saga.","Ensure the rejected payload from the saga is shaped for redux-form (field-keyed, e.g. { usersByRole: '...' } or { _error: '...' }) so errors render on the right field.","If you see a generic 'error' string, inspect the saga's reject() call and the backend response to map the message onto a field.","Handle SubmissionError in the form's onSubmit (redux-form catches it automatically) — do not let it propagate as an uncaught exception."],"exampleFix":"// before\n.catch((error) => { throw new SubmissionError(error); })\n// backend returns { error: 'Invalid email' } -> renders as generic form error\n\n// after (shape the payload for redux-form fields)\n.catch((error) => {\n  throw new SubmissionError({ usersByRole: error.message, _error: error.message });\n})","handlingStrategy":"try-catch","validationCode":"function validEmails(list: string) {\n  return list.split(',').map(s => s.trim()).every(e => /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(e));\n}\nif (!validEmails(values.usersByRole.map(r => r.users).join(','))) {\n  throw new SubmissionError({ usersByRole: 'One or more emails are invalid' });\n}","typeGuard":"const isSubmissionErrorPayload = (e: unknown): e is Record<string, string> =>\n  typeof e === 'object' && e !== null && Object.values(e).every(v => typeof v === 'string');","tryCatchPattern":".catch((error) => {\n  // Map backend payload onto redux-form fields; fall back to _error\n  throw new SubmissionError(isSubmissionErrorPayload(error) ? error : { _error: String(error?.message ?? error) });\n})","preventionTips":["Validate email syntax client-side before dispatching INVITE_USERS_TO_WORKSPACE_INIT.","Always shape the rejected payload as redux-form field errors (or _error).","Let redux-form catch SubmissionError in onSubmit; never let it propagate uncaught."],"tags":["react","redux-form","forms","validation","typescript"],"backgroundTag":null,"analyzedSha":"8cd9021c24cdbea1c3c12c966073708e83db60c2","analyzedAt":"2026-08-12T22:14:19.293Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}