makeplane/plane · error · Error

Member not found

Error message

Member not found

What it means

Workspace-level analogue of [6]: updateMember in the workspace member store throws when getWorkspaceMemberDetails(userId) is falsy. The check protects the optimistic role update and the subsequent updateWorkspaceMember REST call which needs memberDetails.id.

Source

Thrown at apps/web/core/store/member/workspace/workspace-member.store.ts:259

            id: member.id,
            member: member.member.id,
            role: member.role,
            is_active: member.is_active,
          });
        });
      });
      return response;
    });

  /**
   * @description update the role of a workspace member
   * @param workspaceSlug
   * @param userId
   * @param data
   */
  updateMember = async (workspaceSlug: string, userId: string, data: { role: EUserPermissions }) => {
    const memberDetails = this.getWorkspaceMemberDetails(userId);
    if (!memberDetails) throw new Error("Member not found");
    // original data to revert back in case of error
    const originalProjectMemberData = { ...this.workspaceMemberMap?.[workspaceSlug]?.[userId] };
    try {
      runInAction(() => {
        set(this.workspaceMemberMap, [workspaceSlug, userId, "role"], data.role);
      });
      await this.workspaceService.updateWorkspaceMember(workspaceSlug, memberDetails.id, data);
    } catch (error) {
      // revert back to original members in case of error
      runInAction(() => {
        set(this.workspaceMemberMap, [workspaceSlug, userId], originalProjectMemberData);
      });
      throw error;
    }
  };

  /**
   * @description remove a member from workspace

View on GitHub (pinned to 1c8a60f858)

Solutions

  1. Fetch workspace members for the slug before enabling the role dropdown.
  2. Confirm the userId is part of workspaceMemberMap[workspaceSlug]; re-fetch if not.
  3. Verify the workspaceSlug in scope matches the member's actual workspace.
  4. Guard the action at the call site and show a loading/disabled state instead of throwing.

Example fix

// before
const memberDetails = this.getWorkspaceMemberDetails(userId);
if (!memberDetails) throw new Error("Member not found");
// after
const memberDetails = this.getWorkspaceMemberDetails(userId);
if (!memberDetails) { await this.fetchWorkspaceMembers(workspaceSlug); return; }
Defensive patterns

Strategy: validation

Validate before calling

const member = workspaceMemberStore.getWorkspaceMemberDetails(userId);
if (!member) {
  await workspaceMemberStore.fetchWorkspaceMembers(workspaceSlug);
  return;
}

Type guard

const hasWorkspaceMember = (m: unknown): m is { id: string } =>
  typeof m === 'object' && m !== null && typeof (m as any).id === 'string';

Try / catch

try { await updateMember(workspaceSlug, userId, { role }); }
catch (e) { showRoleUpdateError(); }

Prevention

When it happens

Trigger: Changing a workspace member's role before workspaceMemberMap[workspaceSlug][userId] is loaded; the userId is not a workspace member; the member record exists but lacks the fields getWorkspaceMemberDetails expects.

Common situations: Workspace settings page opened via deep link before the members list resolves; member removed concurrently in another tab; cross-workspace confusion (userId valid in workspace A but action fired against workspace B).

Related errors


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