Skip to content

Commit c4f0dcc

Browse files
committed
validate room and return proper error in case it is unknown
1 parent 88da8ff commit c4f0dcc

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

ee/packages/federation-matrix/src/api/_matrix/client/_shared.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@ export const internalError = (msg: string, err?: unknown, context?: Record<strin
1616
};
1717
};
1818

19+
// The federation SDK throws an Error with name 'UnknownRoomError' (message `Room <id> does not exist`)
20+
// when a room isn't known to this homeserver. The class isn't exported for `instanceof`, so we match on
21+
// `.name` — the same check the SDK uses internally.
22+
export const isUnknownRoomError = (err: unknown): err is Error => err instanceof Error && err.name === 'UnknownRoomError';
23+
24+
// Matrix response for a room this homeserver doesn't know about. Mirrors Synapse: it must be a 4xx (never
25+
// 5xx) so bridges like matrix-bifrost treat it as terminal and stop retrying, instead of hammering the
26+
// endpoint every 100ms as if it were a transient server fault.
27+
export const roomNotFound = () =>
28+
({
29+
statusCode: 403 as const,
30+
body: {
31+
errcode: 'M_FORBIDDEN',
32+
error: "You aren't a member of the room and weren't previously a member of the room.",
33+
},
34+
}) as const;
35+
1936
// Logs a warning and returns the matching Matrix 501 response. Use for endpoints/branches
2037
// that are deliberately not implemented yet, so hits on those paths stay visible in the logs.
2138
export const notImplemented = (msg: string, context?: Record<string, unknown>) => {

ee/packages/federation-matrix/src/api/_matrix/client/rooms-state.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import type { ClientRouter } from './_shared';
66
import {
77
MATRIX_ROOM_ID_PATTERN,
88
internalError,
9+
isUnknownRoomError,
910
notImplemented,
11+
roomNotFound,
1012
isImpersonationQueryProps,
1113
isMatrixErrorProps,
1214
isRoomIdParamsProps,
@@ -105,6 +107,9 @@ const getRoomStateEvent = async (roomId: RoomID, eventType: string, stateKey = '
105107
body: pe.getContent(),
106108
};
107109
} catch (error) {
110+
if (isUnknownRoomError(error)) {
111+
return roomNotFound();
112+
}
108113
return internalError('Failed to fetch state event', error);
109114
}
110115
};
@@ -119,7 +124,7 @@ export const addRoomsStateRoutes = (router: ClientRouter) => {
119124
response: {
120125
200: isJoinedMembersResponseProps,
121126
401: isMatrixErrorProps,
122-
404: isMatrixErrorProps,
127+
403: isMatrixErrorProps,
123128
500: isMatrixErrorProps,
124129
},
125130
tags,
@@ -128,6 +133,7 @@ export const addRoomsStateRoutes = (router: ClientRouter) => {
128133
isAppServiceAuthenticatedMiddleware(),
129134
async (c) => {
130135
const roomId = c.req.param('roomId') as RoomID;
136+
131137
try {
132138
const state = await federationSDK.getLatestRoomState(roomId);
133139
const joined: Record<string, { display_name?: string; avatar_url?: string }> = {};
@@ -147,6 +153,9 @@ export const addRoomsStateRoutes = (router: ClientRouter) => {
147153
body: { joined },
148154
};
149155
} catch (error) {
156+
if (isUnknownRoomError(error)) {
157+
return roomNotFound();
158+
}
150159
return internalError('Failed to fetch joined members', error, { roomId });
151160
}
152161
},
@@ -160,7 +169,7 @@ export const addRoomsStateRoutes = (router: ClientRouter) => {
160169
response: {
161170
200: isStateArrayResponseProps,
162171
401: isMatrixErrorProps,
163-
404: isMatrixErrorProps,
172+
403: isMatrixErrorProps,
164173
500: isMatrixErrorProps,
165174
},
166175
tags,
@@ -180,6 +189,9 @@ export const addRoomsStateRoutes = (router: ClientRouter) => {
180189
body: events,
181190
};
182191
} catch (error) {
192+
if (isUnknownRoomError(error)) {
193+
return roomNotFound();
194+
}
183195
return internalError('Failed to fetch room state', error, { roomId });
184196
}
185197
},
@@ -197,6 +209,7 @@ export const addRoomsStateRoutes = (router: ClientRouter) => {
197209
response: {
198210
200: isStateContentResponseProps,
199211
401: isMatrixErrorProps,
212+
403: isMatrixErrorProps,
200213
404: isMatrixErrorProps,
201214
500: isMatrixErrorProps,
202215
},
@@ -220,6 +233,7 @@ export const addRoomsStateRoutes = (router: ClientRouter) => {
220233
response: {
221234
200: isStateContentResponseProps,
222235
401: isMatrixErrorProps,
236+
403: isMatrixErrorProps,
223237
404: isMatrixErrorProps,
224238
500: isMatrixErrorProps,
225239
},

0 commit comments

Comments
 (0)