{"id":"d309aa7d00011ef7","repo":"socketio/socket.io","slug":"ev-tostring-is-a-reserved-event-name","errorCode":null,"errorMessage":"\"${ev.toString()}\" is a reserved event name","messagePattern":"\"(.+?)\" is a reserved event name","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/socket.io-client/lib/socket.ts","lineNumber":415,"sourceCode":"   * @example\n   * socket.emit(\"hello\", \"world\");\n   *\n   * // all serializable datastructures are supported (no need to call JSON.stringify)\n   * socket.emit(\"hello\", 1, \"2\", { 3: [\"4\"], 5: Uint8Array.from([6]) });\n   *\n   * // with an acknowledgement from the server\n   * socket.emit(\"hello\", \"world\", (val) => {\n   *   // ...\n   * });\n   *\n   * @return self\n   */\n  public emit<Ev extends EventNames<EmitEvents>>(\n    ev: Ev,\n    ...args: EventParams<EmitEvents, Ev>\n  ): this {\n    if (RESERVED_EVENTS.hasOwnProperty(ev)) {\n      throw new Error('\"' + ev.toString() + '\" is a reserved event name');\n    }\n\n    args.unshift(ev);\n\n    if (this._opts.retries && !this.flags.fromQueue && !this.flags.volatile) {\n      this._addToQueue(args);\n      return this;\n    }\n\n    const packet: any = {\n      type: PacketType.EVENT,\n      data: args,\n    };\n\n    packet.options = {};\n    packet.options.compress = this.flags.compress !== false;\n\n    // event ack callback","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/socketio/socket.io/blob/ae7fb46e08c5ed964b4a1ea8b1703e816511598e/packages/socket.io-client/lib/socket.ts#L397-L433","documentation":"Thrown by the client Socket.emit() when the event name passed is one of the reserved events: connect, connect_error, disconnect, disconnecting, newListener, removeListener (defined in RESERVED_EVENTS at socket.ts:90). These events are reserved because they are emitted by the library itself to signal lifecycle/EventEmitter internals; allowing user emission would corrupt state and confuse listeners.","triggerScenarios":"Calling socket.emit('connect'), socket.emit('disconnect'), socket.emit('connect_error'), socket.emit('disconnecting'), socket.emit('newListener'), or socket.emit('removeListener') on a client Socket instance.","commonSituations":"Naming a custom event that collides with a lifecycle event (e.g. socket.emit('disconnect') to 'tell' the server it left); copy-pasting a server-side event name to the client without checking the reserved list; or upgrading socket.io-client across a major version that added a new reserved event.","solutions":["Rename your custom event to something not in the reserved list (connect, connect_error, disconnect, disconnecting, newListener, removeListener).","If you need to signal disconnection, call socket.disconnect() instead of socket.emit('disconnect').","If you need to exchange lifecycle-like information, use a distinct event name such as 'user:left'."],"exampleFix":"// before\nsocket.emit('disconnect');\n\n// after\nsocket.emit('user:left');\n// or, to actually close the connection:\nsocket.disconnect();","handlingStrategy":"validation","validationCode":"const RESERVED = new Set(['connect','connect_error','disconnect','disconnecting','newListener','removeListener']);\nfunction assertEmittable(ev){\n  if(RESERVED.has(ev)) throw new Error(ev+' is reserved');\n}","typeGuard":"function isEmittableEvent(ev){\n  return !['connect','connect_error','disconnect','disconnecting','newListener','removeListener'].includes(ev);\n}","tryCatchPattern":null,"preventionTips":["Never name custom events connect/connect_error/disconnect/disconnecting/newListener/removeListener on the client.","Use socket.disconnect() to disconnect, not socket.emit('disconnect').","Check the reserved list after upgrading socket.io-client major versions."],"tags":["client","emit","reserved-events","lifecycle"],"analyzedSha":"ae7fb46e08c5ed964b4a1ea8b1703e816511598e","analyzedAt":"2026-08-03T19:08:14.127Z","schemaVersion":2}