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
- Check TeamResponse.joinPolicy === 'OPEN' before offering self-join; otherwise route the user to 'request invite'
- An admin adds the user with POST .../workspaces/{ws_id}/members (add_team_member has no OPEN requirement)
- An admin flips the workspace joinPolicy to 'OPEN' via PATCH if open enrollment is intended
- 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
- Gate join buttons on joinPolicy === 'OPEN'
- Keep an invite/request-access path for PRIVATE workspaces
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
- Workspace does not belong to this organization
- User {user_id} is not a member of the organization
- Cannot change the default workspace's join policy
- Cannot delete the default workspace
- Cannot leave the default workspace
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/23e20599da2e164d.
Report an issue: GitHub.