RocketChat/Rocket.Chat · error · Error

error-invalid-team-not-a-member

Error message

error-invalid-team-not-a-member

What it means

Thrown by TeamService.listChildren when the requesting user has no TeamMember document for the team — membership is checked with TeamMember.findOneByUserIdAndTeamId before listing team rooms. Team room listings (joined channels + public team channels + main-room discussions) are member-only. It fires after the main-room existence check.

Source

Thrown at apps/meteor/server/services/team/service.ts:1099

		userId: string,
		team: AtLeast<ITeam, '_id' | 'roomId' | 'type'>,
		filter?: string,
		type?: 'channels' | 'discussions',
		sort?: Record<string, 1 | -1>,
		skip = 0,
		limit = 10,
	): Promise<{ total: number; data: IRoom[] }> {
		const mainRoom = await Rooms.findOneById(team.roomId, { projection: { _id: 1 } });
		if (!mainRoom) {
			throw new Error('error-invalid-team-no-main-room');
		}

		const isMember = await TeamMember.findOneByUserIdAndTeamId(userId, team._id, {
			projection: { _id: 1 },
		});

		if (!isMember) {
			throw new Error('error-invalid-team-not-a-member');
		}

		const [{ totalCount: [{ count: total }] = [], paginatedResults: data = [] }] =
			(await Rooms.findChildrenOfTeam(team._id, mainRoom._id, userId, filter, type, { skip, limit, sort }).toArray()) || [];

		return {
			total,
			data,
		};
	}
}

View on GitHub (pinned to e4b8178b20)

Solutions

  1. Verify membership first: TeamMember.findOneByUserIdAndTeamId(userId, teamId)
  2. Re-fetch the user's teams (teams.list for the current user) and drop stale entries from the UI
  3. Rejoin the team or request an invite if access is expected
  4. For tooling, add the service account to the team before enumerating its rooms

Example fix

// before
const rooms = await Teams.listChildren(userId, team);

// after
const isMember = await TeamMember.findOneByUserIdAndTeamId(userId, team._id, { projection: { _id: 1 } });
if (!isMember) throw new Error('error-invalid-team-not-a-member');
const rooms = await Teams.listChildren(userId, team);
Defensive patterns

Strategy: validation

Validate before calling

const isMember = await TeamMember.findOneByUserIdAndTeamId(userId, teamId, { projection: { _id: 1 } });
if (!isMember) {
  return API.v1.unauthorized(); // or hide the team from the user's listings
}

Try / catch

try {
  const rooms = await Teams.listChildren(userId, team);
} catch (err) {
  if (err instanceof Error && err.message === 'error-invalid-team-not-a-member') {
    // refresh the team list; remove the team from the sidebar
  }
  throw err;
}

Prevention

When it happens

Trigger: Listing rooms of a team the user never joined; the user was just removed but the client still shows the team; a script iterates all teams under one service account that belongs to none; membership records lost during migration.

Common situations: Stale UI after membership revocation; token reuse across users in tests; admin tooling using a non-member bot account.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@e4b8178b20 (2026-08-18). Data as JSON: /api/errors/6703bdc4e5314ca4. Report an issue: GitHub.