Significant-Gravitas/AutoGPT · error · HTTPException
Teams not found in this organization: {invalid}
Error message
Teams not found in this organization: {invalid} What it means
Raised by POST /api/orgs/{org_id}/invitations when one or more team_ids in InvitationCreateRequest do not reference teams that exist in the database and belong to the org in the URL path. The check exists because the accept path's add_team_member re-validates and silently skips failures, so a poisoned invitation would only fail quietly at accept time; the create endpoint fails loudly instead. It is an HTTP 400 HTTPException.
Source
Thrown at autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py:61
org_id: str,
request: CreateInvitationRequest,
ctx: Annotated[
RequestContext,
Security(requires_org_permission(OrgAction.MANAGE_MEMBERS)),
],
) -> InvitationCreateResponse:
_verify_org_path(ctx, org_id)
# Reject team IDs outside this org at create time. The accept path's
# add_team_member re-validates (and silently skips failures), so
# without this check a poisoned invitation would fail silently at
# accept instead of loudly at create.
if request.team_ids:
teams = await prisma.team.find_many(where={"id": {"in": request.team_ids}})
valid_ids = {t.id for t in teams if t.orgId == org_id}
invalid = [t for t in request.team_ids if t not in valid_ids]
if invalid:
raise HTTPException(
400,
detail=f"Teams not found in this organization: {invalid}",
)
expires_at = datetime.now(timezone.utc) + timedelta(days=INVITATION_TTL_DAYS)
invitation = await prisma.orginvitation.create(
data={
"orgId": org_id,
"email": request.email,
"isAdmin": request.is_admin,
"isBillingManager": request.is_billing_manager,
"expiresAt": expires_at,
"invitedByUserId": ctx.user_id,
"teamIds": request.team_ids,
}
)
View on GitHub (pinned to 9c8bb5550f)
Solutions
- Re-fetch the team list for the current org (GET /api/orgs/{org_id}/teams) immediately before submitting and rebuild team_ids from it.
- Verify every team_id in the request payload matches an id from that org's team list; drop or fix any that do not.
- If the team should exist, check the Team table (prisma.team) for the id and confirm its orgId equals the org_id in the URL path.
- Handle the 400 by parsing the detail list of invalid IDs and refreshing the user's team selection UI.
Example fix
// before
const res = await api.post(`/api/orgs/${orgId}/invitations`, {
email, team_ids: selectedTeamIds, // may contain stale ids
});
// after
const teams = await api.get(`/api/orgs/${orgId}/teams`).then(r => r.data);
const validIds = new Set(teams.map(t => t.id));
const team_ids = selectedTeamIds.filter(id => validIds.has(id));
if (selectedTeamIds.length !== team_ids.length) {
throw new Error('Some selected teams no longer exist in this organization');
}
const res = await api.post(`/api/orgs/${orgId}/invitations`, { email, team_ids }); Defensive patterns
Strategy: validation
Validate before calling
const teams = await api.get(`/api/orgs/${orgId}/teams`).then(r => r.data);
const validIds = new Set(teams.map(t => t.id));
const ok = selectedTeamIds.every(id => validIds.has(id));
if (!ok) throw new Error('Invalid team ids for this org'); Try / catch
try {
await api.post(`/api/orgs/${orgId}/invitations`, payload);
} catch (e) {
if (e.status === 400 && /Teams not found/.test(e.detail)) {
const invalid = JSON.parse(e.detail.split(': ')[1]); // ids to drop
await refreshTeams();
} else throw e;
} Prevention
- Always build team_ids from a fresh org-scoped team list at submit time
- Drop cached team ids when the active org changes
- Parse the 400 detail list to auto-heal the picker
When it happens
Trigger: Calling create invitation with team_ids that are deleted, typo'd, belong to a different organization, or were created in another org (valid_ids filters on t.orgId == org_id). Also triggered when the caller copies team IDs from a different environment (staging IDs used against production).
Common situations: Frontend sends stale team IDs cached from a previous org switch; team was deleted between the picker load and form submit; test fixtures use hardcoded team IDs that drift after migrations; multi-tenant confusion where X-Org-Id header org differs from the team's org.
Related errors
- start and end query params are required
- str(exc)
- Either user_id or email query parameter is required.
- Search query must be at least 3 characters.
- Unsupported grant_type: {request.grant_type}. Must be 'autho
AI-assisted analysis of Significant-Gravitas/AutoGPT@9c8bb5550f (2026-08-14).
Data as JSON: /api/errors/8d2222dfea5521d8.
Report an issue: GitHub.