Significant-Gravitas/AutoGPT · error · ValueError

Cannot self-join a PRIVATE workspace. Request an invite.

Error message

Cannot self-join a PRIVATE workspace. Request an invite.

What it means

Raised by team_db.join_team when the workspace's joinPolicy is anything other than 'OPEN' (currently 'PRIVATE'). Self-join is only allowed on open workspaces; private ones require an explicit invitation via the invite/add-member flow. Plain ValueError from the DB layer.

Source

Thrown at autogpt_platform/backend/backend/api/features/orgs/team_db.py:105

    """Delete a workspace. Cannot delete the default workspace."""
    ws = await prisma.team.find_unique(where={"id": ws_id})
    if ws is None:
        raise NotFoundError(f"Workspace {ws_id} not found")
    if ws.isDefault:
        raise ValueError("Cannot delete the default workspace")

    await prisma.team.delete(where={"id": ws_id})


async def join_team(ws_id: str, user_id: str, org_id: str) -> TeamResponse:
    """Self-join an OPEN workspace. User must be an org member."""
    ws = await prisma.team.find_unique(where={"id": ws_id})
    if ws is None:
        raise NotFoundError(f"Workspace {ws_id} not found")
    if ws.orgId != org_id:
        raise ValueError("Workspace does not belong to this organization")
    if ws.joinPolicy != "OPEN":
        raise ValueError("Cannot self-join a PRIVATE workspace. Request an invite.")

    # Verify user is actually an org member
    org_member = await prisma.orgmember.find_unique(
        where={"orgId_userId": {"orgId": org_id, "userId": user_id}}
    )
    if org_member is None:
        raise ValueError(f"User {user_id} is not a member of the organization")

    # Check not already a member
    existing = await prisma.teammember.find_unique(
        where={"teamId_userId": {"teamId": ws_id, "userId": user_id}}
    )
    if existing:
        return TeamResponse.from_db(ws)

    await prisma.teammember.create(
        data={
            "teamId": ws_id,

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Check TeamResponse.joinPolicy === 'OPEN' before offering self-join; otherwise route the user to 'request invite'
  2. An admin adds the user with POST .../workspaces/{ws_id}/members (add_team_member has no OPEN requirement)
  3. An admin flips the workspace joinPolicy to 'OPEN' via PATCH if open enrollment is intended
  4. Link the user to the invitation flow instead of the /join endpoint for PRIVATE workspaces

Example fix

// before
{workspaces.map(ws => <JoinButton onClick={() => join(ws.id)} />)}
// after
{workspaces.map(ws =>
  ws.joinPolicy === 'OPEN'
    ? <JoinButton onClick={() => join(ws.id)} />
    : <RequestInviteButton wsId={ws.id} />
)}
Defensive patterns

Strategy: validation

Validate before calling

const ws = await getWorkspace(orgId, wsId);
if (ws.joinPolicy !== 'OPEN') {
  redirectToAddMemberOrInviteFlow(wsId);
}

Type guard

function isJoinableWorkspace(ws: TeamResponse): boolean {
  return ws.joinPolicy === 'OPEN';
}

Try / catch

try {
  await joinTeam(orgId, wsId);
} catch (e) {
  if (e.message.includes('PRIVATE workspace')) {
    showToast('This workspace is invite-only — request an invite.');
  } else throw e;
}

Prevention

When it happens

Trigger: POST /api/orgs/{org_id}/workspaces/{ws_id}/join where the workspace was created (or updated) with join_policy='PRIVATE'. The check runs after the workspace exists and belongs to the org, so the caller is otherwise eligible.

Common situations: UI showing a 'Join' button on every workspace in the directory without filtering on joinPolicy; policy recently changed from OPEN to PRIVATE while users still have old links; users expecting org membership to imply workspace access.

Related errors


AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14). Data as JSON: /api/errors/23e20599da2e164d. Report an issue: GitHub.