{"record":{"id":"80dbc630943c2ee9","repo":"RocketChat/Rocket.Chat","slug":"invalid-username","errorCode":null,"errorMessage":"Invalid username","messagePattern":"Invalid username","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/app/apps/server/bridges/messages.ts","lineNumber":110,"sourceCode":"\t\t// #TODO: #AppsEngineTypes - Remove explicit types and typecasts once the apps-engine definition/implementation mismatch is fixed.\n\t\tconst msg: IMessage | undefined = await this.orch.getConverters()?.get('messages').convertAppMessage(message);\n\t\tconst convertedMessage = msg as IMessage;\n\n\t\tconst users = (await Subscriptions.findByRoomIdWhenUserIdExists(room.id, { projection: { 'u._id': 1 } }).toArray()).map((s) => s.u._id);\n\n\t\tawait Users.findByIds(users, { projection: { _id: 1 } }).forEach(\n\t\t\t({ _id }: { _id: string }) =>\n\t\t\t\tvoid api.broadcast('notify.ephemeralMessage', _id, room.id, {\n\t\t\t\t\t...convertedMessage,\n\t\t\t\t}),\n\t\t);\n\t}\n\n\tprotected async typing({ scope, id, username, isTyping }: ITypingDescriptor): Promise<void> {\n\t\tswitch (scope) {\n\t\t\tcase 'room':\n\t\t\t\tif (!username) {\n\t\t\t\t\tthrow new Error('Invalid username');\n\t\t\t\t}\n\n\t\t\t\tnotifications.notifyRoom(id, 'user-activity', username, isTyping ? ['user-typing'] : []);\n\t\t\t\treturn;\n\t\t\tdefault:\n\t\t\t\tthrow new Error('Unrecognized typing scope provided');\n\t\t}\n\t}\n\n\tprivate isValidReaction(reaction: Reaction): boolean {\n\t\treturn reaction.startsWith(':') && reaction.endsWith(':');\n\t}\n\n\tprotected async addReaction(messageId: string, userId: string, reaction: Reaction): Promise<void> {\n\t\tif (!this.isValidReaction(reaction)) {\n\t\t\tthrow new Error('Invalid reaction');\n\t\t}\n","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/app/apps/server/bridges/messages.ts#L92-L128","documentation":"Thrown by AppMessageBridge.typing when scope is 'room' but username is falsy. Room-scoped typing notifications are broadcast under a username, so the bridge cannot emit the user-activity event without one and rejects the call. It is a precondition on the typing descriptor for room scope.","triggerScenarios":"An App calls the typing notifier (e.g. app.getModify().typing(...)) with scope 'room' and username undefined/null/empty, e.g. the App did not set the typing user's username.","commonSituations":"App constructs an ITypingDescriptor without username; App reads the user from context where username is absent; App confuses userId with username; refactoring dropped the username field.","solutions":["Set username to the typing user's username whenever scope is 'room'.","Resolve the user via the read accessor and use its username field.","Add a guard: if (scope === 'room' && !username) fail fast with a clear message.","Validate the ITypingDescriptor shape before calling the notifier."],"exampleFix":"// before\nawait app.getModify().typing({ scope: 'room', id: room.id, username: undefined, isTyping: true });\n\n// after\nif (!user.username) {\n  throw new Error('Cannot send typing indicator without a username');\n}\nawait app.getModify().typing({ scope: 'room', id: room.id, username: user.username, isTyping: true });","handlingStrategy":"validation","validationCode":"function assertRoomTypingDescriptor(descriptor: ITypingDescriptor): asserts descriptor is ITypingDescriptor & { username: string } {\n  if (descriptor.scope === 'room' && !descriptor.username) {\n    throw new Error('Room-scoped typing requires a username');\n  }\n}\nassertRoomTypingDescriptor(descriptor);\nawait app.getModify().typing(descriptor);","typeGuard":"const isRoomTypingWithUsername = (d: ITypingDescriptor): d is ITypingDescriptor & { scope: 'room'; username: string } =>\n  d.scope === 'room' && typeof d.username === 'string' && d.username.length > 0;","tryCatchPattern":"try {\n  await app.getModify().typing(descriptor);\n} catch (e) {\n  if ((e as Error).message === 'Invalid username') {\n    // resolve the user's username and retry\n  }\n  throw e;\n}","preventionTips":["Always set username for room-scoped typing descriptors.","Resolve the user via the read accessor and use its username field.","Validate the ITypingDescriptor shape before calling the notifier."],"tags":["apps-engine","message","typing","validation","username"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}