{"record":{"id":"fbc09b7a16bb5824","repo":"stablyai/orca","slug":"invalid-orca-org-role","errorCode":null,"errorMessage":"invalid_orca_org_role","messagePattern":"invalid_orca_org_role","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/orca-profile-org-members-handlers.ts","lineNumber":37,"sourceCode":"} from '../orca-profiles/profile-cloud-org-members-service'\n\nfunction orgMembersScopedArgs(args: unknown): { orgId: string; record: Record<string, unknown> } {\n  if (!args || typeof args !== 'object') {\n    throw new Error('invalid_orca_profile_org_selection')\n  }\n  const record = args as Record<string, unknown>\n  const orgId = typeof record.orgId === 'string' ? record.orgId.trim() : ''\n  if (!orgId) {\n    throw new Error('invalid_orca_profile_org_selection')\n  }\n  return { orgId, record }\n}\n\nfunction orgRoleFromUnknown(value: unknown): OrcaOrgRole {\n  if (value === 'owner' || value === 'admin' || value === 'member') {\n    return value\n  }\n  throw new Error('invalid_orca_org_role')\n}\n\nfunction orgEmailFromUnknown(value: unknown): string {\n  const email = typeof value === 'string' ? value.trim() : ''\n  if (!email) {\n    throw new Error('invalid_orca_org_member_email')\n  }\n  return email\n}\n\nfunction orgUserIdFromUnknown(value: unknown): string {\n  const userId = typeof value === 'string' ? value.trim() : ''\n  if (!userId) {\n    throw new Error('invalid_orca_org_member_user')\n  }\n  return userId\n}\n","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/orca-profile-org-members-handlers.ts#L19-L55","documentation":"Thrown by orgRoleFromUnknown() when the role value on an invite or role-change payload is not one of the literal string values 'owner', 'admin', or 'member'. The function narrows an untrusted renderer input to the OrcaOrgRole union; any other value (including typos like 'Owner' with capital, 'guest', numbers, or undefined) is rejected before reaching the cloud org-members service.","triggerScenarios":"Calling orcaProfiles:orgMemberInvite or orcaProfiles:orgMemberChangeRole with a role field that is missing, undefined, or any string other than exactly 'owner', 'admin', or 'member'. Capitalized variants and synonyms are rejected.","commonSituations":"Role dropdown emits a display label ('Administrator') instead of the canonical value, a serialized enum from a different schema leaks in, or a new role was added to the cloud API but the main-process allowlist has not been updated.","solutions":["Send the lowercase canonical role string exactly: 'owner' | 'admin' | 'member' — no capitalization, no synonyms.","Map UI role labels to canonical ids at the dropdown boundary and pass the id, not the label.","If a new role is genuinely supported upstream, add it to the literal union in shared/orca-profiles (OrcaOrgRole) and to this guard in lockstep.","Default the invite role to 'member' when the picker has no explicit selection, rather than sending undefined."],"exampleFix":"// before\nawait ipcRenderer.invoke('orcaProfiles:orgMemberInvite', { orgId, email, role: roleSelect.value })\n\n// after\nconst ROLES = ['owner', 'admin', 'member'] as const\nconst role = ROLES.includes(roleSelect.value) ? roleSelect.value : 'member'\nawait ipcRenderer.invoke('orcaProfiles:orgMemberInvite', { orgId, email, role })","handlingStrategy":"type-guard","validationCode":"const ORG_ROLES = ['owner', 'admin', 'member'] as const\ntype OrgRole = typeof ORG_ROLES[number]\n\nfunction toOrgRole(v: unknown): OrgRole {\n  return ORG_ROLES.includes(v as OrgRole) ? (v as OrgRole) : 'member'\n}","typeGuard":"function isOrgRole(v: unknown): v is 'owner' | 'admin' | 'member' {\n  return v === 'owner' || v === 'admin' || v === 'member'\n}","tryCatchPattern":"try {\n  await ipcRenderer.invoke('orcaProfiles:orgMemberInvite', { orgId, email, role })\n} catch (e) {\n  if (e instanceof Error && e.message === 'invalid_orca_org_role') {\n    setRoleError('Role must be owner, admin, or member.')\n  } else throw e\n}","preventionTips":["Render the role dropdown from the same constant array the guard uses.","Map UI labels to canonical role ids at the select boundary.","When adding a cloud role, update the OrcaOrgRole union and this guard atomically."],"tags":["ipc","validation","orca-profiles","enum-narrowing","argument-validation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}