Significant-Gravitas/AutoGPT · error · ValueError

Workspace does not belong to this organization

Error message

Workspace does not belong to this organization

What it means

Raised by team_db.join_team when the found workspace's orgId does not equal the org_id passed in. It prevents joining a workspace through the wrong organization's URL scope. Plain ValueError from the DB layer.

Source

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

async def delete_team(ws_id: str) -> None:
    """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(

View on GitHub (pinned to 9c8bb5550f)

Solutions

  1. Always derive ws_id and org_id from the same TeamResponse object (its orgId field) when constructing the join URL
  2. Re-fetch the workspace via GET /api/orgs/{org_id}/workspaces and use the returned id
  3. In the client, catch this and reset the user's active-org/workspace selection so links are rebuilt consistently
  4. Audit generated links/emails to embed both ids from one source

Example fix

// before
const url = `/api/orgs/${activeOrgId}/workspaces/${cachedWsId}/join`;
// after
const ws = await getWorkspace(activeOrgId, cachedWsId); // 404/does-not-belong if stale
const url = `/api/orgs/${ws.orgId}/workspaces/${ws.id}/join`;
Defensive patterns

Strategy: validation

Validate before calling

const ws = await getWorkspace(orgId, wsId).catch(() => null);
if (!ws || ws.orgId !== orgId) throw new Error('Workspace does not belong to this org');

Type guard

function workspaceInOrg(ws: TeamResponse, orgId: string): boolean {
  return ws.orgId === orgId;
}

Try / catch

try {
  await joinTeam(orgId, wsId);
} catch (e) {
  if (e.message.includes('does not belong to this organization')) {
    // reset active org/workspace selection and rebuild the URL
  } else throw e;
}

Prevention

When it happens

Trigger: POST /api/orgs/{org_id}/workspaces/{ws_id}/join where ws_id belongs to a different org than org_id in the path. Typically a URL assembled from mixed sources (org id from one context, workspace id from another), or after a workspace was moved/recreated under another org.

Common situations: Deep links or bookmarks built from a previous org context; multi-org clients where the active org switch did not refresh workspace references; test fixtures that pair unrelated org and workspace ids.

Related errors


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