Can't Get Floodgate+Geyser to Work on Second Instance

OS Name/Version: Ubuntu 20.04.4 LTS

Product Name/Version: 2.3.2.12

Problem Description:

I have a Minecraft Java instance running succesfully with Floodgate+Geyser plugins (manual install).

I have now started a second Minecraft Java instance and want to use the same plugins for this instance, too. I have changed the port number in the plugins/Geyser-Spigot/config.yml to the new port number for this instance. Everything else should be the same left as defaults, but here is the complete file:

# --------------------------------
# Geyser Configuration File
#
# A bridge between Minecraft: Bedrock Edition and Minecraft: Java Edition.
#
# GitHub: https://github.com/GeyserMC/Geyser
# Discord: https://discord.geysermc.org/
# --------------------------------

bedrock:
  # The IP address that will listen for connections.
  # There is no reason to change this unless you want to limit what IPs can connect to your server.
  address: 0.0.0.0
  # The port that will listen for connections
  port: 35571
  # Some hosting services change your Java port everytime you start the server and require the same port to be used for Bedrock.
  # This option makes the Bedrock port the same as the Java port every time you start the server.
  # This option is for the plugin version only.
  clone-remote-port: false
  # The MOTD that will be broadcasted to Minecraft: Bedrock Edition clients. This is irrelevant if "passthrough-motd" is set to true
  # If either of these are empty, the respective string will default to "Geyser"
  motd1: "Powered by McAwesome"
  motd2: "McAwesome Java Server"
  # The Server Name that will be sent to Minecraft: Bedrock Edition clients. This is visible in both the pause menu and the settings menu.
  server-name: "CarsonsJava7"
  # How much to compress network traffic to the Bedrock client. The higher the number, the more CPU usage used, but
  # the smaller the bandwidth used. Does not have any effect below -1 or above 9. Set to -1 to disable.
  compression-level: 6
  # Whether to enable PROXY protocol or not for clients. You DO NOT WANT this feature unless you run UDP reverse proxy
  # in front of your Geyser instance.
  enable-proxy-protocol: false
  # A list of allowed PROXY protocol speaking proxy IP addresses/subnets. Only effective when "enable-proxy-protocol" is enabled, and
  # should really only be used when you are not able to use a proper firewall (usually true with shared hosting providers etc.).
  # Keeping this list empty means there is no IP address whitelist.
  # Both IP addresses and subnets are supported.
  #proxy-protocol-whitelisted-ips: [ "127.0.0.1", "172.18.0.0/16" ]
remote:
  # The IP address of the remote (Java Edition) server
  # If it is "auto", for standalone version the remote address will be set to 127.0.0.1,
  # for plugin versions, it is recommended to keep this as "auto" so Geyser will automatically configure address, port, and auth-type.
  # Leave as "auto" if floodgate is installed.
  address: auto
  # The port of the remote (Java Edition) server
  # For plugin versions, if address has been set to "auto", the port will also follow the server's listening port.
  port: 35571
  # Authentication type. Can be offline, online, or floodgate (see https://github.com/GeyserMC/Geyser/wiki/Floodgate).
  # For plugin versions, it's recommended to keep the `address` field to "auto" so Floodgate support is automatically configured.
  # If Floodgate is installed and `address:` is set to "auto", then "auth-type: floodgate" will automatically be used.
  auth-type: floodgate
  # Allow for password-based authentication methods through Geyser. Only useful in online mode.
  # If this is false, users must authenticate to Microsoft using a code provided by Geyser on their desktop.
  allow-password-authentication: false
  # Whether to enable PROXY protocol or not while connecting to the server.
  # This is useful only when:
  # 1) Your server supports PROXY protocol (it probably doesn't)
  # 2) You run Velocity or BungeeCord with the option enabled in the proxy's main config.
  # IF YOU DON'T KNOW WHAT THIS IS, DON'T TOUCH IT!
  use-proxy-protocol: false
  # Forward the hostname that the Bedrock client used to connect over to the Java server
  # This is designed to be used for forced hosts on proxies
  forward-hostname: false

# Floodgate uses encryption to ensure use from authorised sources.
# This should point to the public key generated by Floodgate (BungeeCord, Spigot or Velocity)
# You can ignore this when not using Floodgate.
# If you're using a plugin version of Floodgate on the same server, the key will automatically be picked up from Floodgate.
floodgate-key-file: key.pem

# For online mode authentication type only.
# Stores a list of Bedrock players that should have their Java Edition account saved after login.
# This saves a token that can be reused to authenticate the player later. This does not save emails or passwords,
# but you should still be cautious when adding to this list and giving others access to this Geyser instance's files.
# Removing a name from this list will delete its cached login information on the next Geyser startup.
# The file for this is in the same folder as this config, named "saved-refresh-tokens.json".
saved-user-logins:
  - ThisExampleUsernameShouldBeLongEnoughToNeverBeAnXboxUsername
  - ThisOtherExampleUsernameShouldAlsoBeLongEnough

# Specify how many seconds to wait while user authorizes Geyser to access their Microsoft account.
# User is allowed to disconnect from the server during this period.
pending-authentication-timeout: 120

# Bedrock clients can freeze when opening up the command prompt for the first time if given a lot of commands.
# Disabling this will prevent command suggestions from being sent and solve freezing for Bedrock clients.
command-suggestions: true

# The following three options enable "ping passthrough" - the MOTD, player count and/or protocol name gets retrieved from the Java server.
# Relay the MOTD from the remote server to Bedrock players.
passthrough-motd: true
# Relay the protocol name (e.g. BungeeCord [X.X], Paper 1.X) - only really useful when using a custom protocol name!
# This will also show up on sites like MCSrvStatus. <mcsrvstat.us>
passthrough-protocol-name: false
# Relay the player count and max players from the remote server to Bedrock players.
passthrough-player-counts: false
# Enable LEGACY ping passthrough. There is no need to enable this unless your MOTD or player count does not appear properly.
# This option does nothing on standalone.
legacy-ping-passthrough: false
# How often to ping the remote server, in seconds. Only relevant for standalone or legacy ping passthrough.
# Increase if you are getting BrokenPipe errors.
ping-passthrough-interval: 3

# Whether to forward player ping to the server. While enabling this will allow Bedrock players to have more accurate
# ping, it may also cause players to time out more easily.
forward-player-ping: false

# Maximum amount of players that can connect. This is only visual at this time and does not actually limit player count.
max-players: 100

# If debug messages should be sent through console
debug-mode: false

# Allow third party capes to be visible. Currently allowing:
# OptiFine capes, LabyMod capes, 5Zig capes and MinecraftCapes
allow-third-party-capes: true

# Allow third party deadmau5 ears to be visible. Currently allowing:
# MinecraftCapes
allow-third-party-ears: false

# Allow a fake cooldown indicator to be sent. Bedrock players do not see a cooldown as they still use 1.8 combat
# Can be title, actionbar or false
show-cooldown: title

# Controls if coordinates are shown to players.
show-coordinates: true

# Whether Bedrock players are blocked from performing their scaffolding-style bridging.
disable-bedrock-scaffolding: false

# Whether Bedrock players can right-click outside of their inventory to replace armor in their inventory, even if the
# armor slot is already occupied (which Java Edition doesn't allow)
always-quick-change-armor: false

# If set, when a Bedrock player performs any emote, it will swap the offhand and mainhand items, just like the Java Edition keybind
# There are three options this can be set to:
# disabled - the default/fallback, which doesn't apply this workaround
# no-emotes - emotes will NOT be sent to other Bedrock clients and offhand will be swapped. This effectively disables all emotes from being seen.
# emotes-and-offhand - emotes will be sent to Bedrock clients and offhand will be swapped
emote-offhand-workaround: "disabled"

# The default locale if we dont have the one the client requested. Uncomment to not use the default system language.
# default-locale: en_us

# Specify how many days images will be cached to disk to save downloading them from the internet.
# A value of 0 is disabled. (Default: 0)
cache-images: 0

# Allows custom skulls to be displayed. Keeping them enabled may cause a performance decrease on older/weaker devices.
allow-custom-skulls: true

# Whether to add (at this time, only) the furnace minecart as a separate item in the game, which normally does not exist in Bedrock Edition.
# This should only need to be disabled if using a proxy that does not use the "transfer packet" style of server switching.
# If this is disabled, furnace minecart items will be mapped to hopper minecart items.
# This option requires a restart of Geyser in order to change its setting.
add-non-bedrock-items: true

# Bedrock prevents building and displaying blocks above Y127 in the Nether.
# This config option works around that by changing the Nether dimension ID to the End ID. 
# The main downside to this is that the entire Nether will have the same red fog rather than having different fog for each biome.
above-bedrock-nether-building: false

# Force clients to load all resource packs if there are any.
# If set to false, it allows the user to connect to the server even if they don't
# want to download the resource packs.
force-resource-packs: true

# Allows Xbox achievements to be unlocked.
# THIS DISABLES ALL COMMANDS FROM SUCCESSFULLY RUNNING FOR BEDROCK IN-GAME, as otherwise Bedrock thinks you are cheating.
xbox-achievements-enabled: false

# bStats is a stat tracker that is entirely anonymous and tracks only basic information
# about Geyser, such as how many people are online, how many servers are using Geyser,
# what OS is being used, etc. You can learn more about bStats here: https://bstats.org/.
# https://bstats.org/plugin/server-implementation/GeyserMC
metrics:
  # If metrics should be enabled
  enabled: true
  # UUID of server, don't change!
  uuid: 8153d521-7a1e-4564-bbd4-816cb1d36536

# ADVANCED OPTIONS - DO NOT TOUCH UNLESS YOU KNOW WHAT YOU ARE DOING!

# Geyser updates the Scoreboard after every Scoreboard packet, but when Geyser tries to handle
# a lot of scoreboard packets per second can cause serious lag.
# This option allows you to specify after how many Scoreboard packets per seconds
# the Scoreboard updates will be limited to four updates per second.
scoreboard-packet-threshold: 20

# Allow connections from ProxyPass and Waterdog.
# See https://www.spigotmc.org/wiki/firewall-guide/ for assistance - use UDP instead of TCP.
enable-proxy-connections: false

# The internet supports a maximum MTU of 1492 but could cause issues with packet fragmentation.
# 1400 is the default.
mtu: 1400

# Whether to connect directly into the Java server without creating a TCP connection.
# This should only be disabled if a plugin that interfaces with packets or the network does not work correctly with Geyser.
# If enabled on plugin versions, the remote address and port sections are ignored
# If disabled on plugin versions, expect performance decrease and latency increase
use-direct-connection: true

config-version: 4

I have tried a few things to workaround this, but can’t figure out why it would matter. I have changed the address from 0.0.0.0 to 127.0.0.1 and 127.0.0.2 in the bedrock: section, and changed the address from auto to 127.0.0.1 and 127.0.0.2 in the remote: section.

Incidentally, the port settings on the first instance are set to 35565.

Both instances are using Docker, so Floodgate+Geyser should be completely isolated from the host.

Here is the mostly unhelpful log I get when starting the instance:


Console19:34:00
Starting org.bukkit.craftbukkit.Main
19:34:01
System Info: Java 17 (OpenJDK 64-Bit Server VM 17.0.2+8-Debian-1deb11u1) Host: Linux 5.4.0-110-generic (amd64)
Loading libraries, please wait...
INFO19:34:08
Environment: authHost='https://authserver.mojang.com', accountsHost='https://api.mojang.com', sessionHost='https://sessionserver.mojang.com', servicesHost='https://api.minecraftservices.com', name='PROD'
19:34:10
Loaded 7 recipes
19:34:12
Starting minecraft server version 1.18.2
Loading properties
This server is running Paper version git-Paper-333 (MC: 1.18.2) (Implementing API version 1.18.2-R0.1-SNAPSHOT) (Git: 9fd870d)
Server Ping Player Sample Count: 12
Using 4 threads for Netty based IO
Default game type: SURVIVAL
Generating keypair
19:34:13
Starting Minecraft server on 0.0.0.0:35571
Using epoll channel type
Paper: Using libdeflate (Linux x86_64) compression from Velocity.
Paper: Using OpenSSL 1.1.x (Linux x86_64) cipher from Velocity.
[floodgate]: Loading floodgate v2.1.0-SNAPSHOT
19:34:14
[floodgate]: Took 573ms to boot Floodgate
[Geyser-Spigot]: Loading Geyser-Spigot v2.0.3-SNAPSHOT
Server permissions file permissions.yml is empty, ignoring it
Preparing level "world"
19:34:15
Preparing start region for dimension minecraft:overworld
19:34:16
Time elapsed: 448 ms
Preparing start region for dimension minecraft:the_nether
Time elapsed: 281 ms
Preparing start region for dimension minecraft:the_end
Time elapsed: 229 ms
[floodgate]: Enabling floodgate v2.1.0-SNAPSHOT
19:34:17
[Geyser-Spigot]: Enabling Geyser-Spigot v2.0.3-SNAPSHOT
19:34:18
[Geyser-Spigot]: Auto-loaded Floodgate key
[Geyser-Spigot]: ******************************************
[Geyser-Spigot]
[Geyser-Spigot]: Loading Geyser version 2.0.3-SNAPSHOT (git-master-31a84ea)
[Geyser-Spigot]
[Geyser-Spigot]: ******************************************
WARN19:34:23
at java.base/java.util.concurrent.CompletableFuture$CoCompletion.tryFire(CompletableFuture.java:1219)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162)
at Geyser-Spigot.jar//com.nukkitx.network.util.Bootstraps.lambda$allOf$0(Bootstraps.java:111)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578)
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:552)
at io.netty.util.concurrent.DefaultPromise.access$200(DefaultPromise.java:35)
at io.netty.util.concurrent.DefaultPromise$1.run(DefaultPromise.java:502)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:384)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: io.netty.channel.unix.Errors$NativeIoException: bind(..) failed: Address already in use
ERROR19:34:23
Error occurred while enabling Geyser-Spigot v2.0.3-SNAPSHOT (Is it up to date?)
Console19:34:23
java.util.concurrent.CompletionException: io.netty.channel.unix.Errors$NativeIoException: bind(..) failed: Address already in use
at java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:332) ~[?:?]
at java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:347) ~[?:?]
at java.util.concurrent.CompletableFuture$BiRelay.tryFire(CompletableFuture.java:1498) ~[?:?]
at java.util.concurrent.CompletableFuture$CoCompletion.tryFire(CompletableFuture.java:1219) ~[?:?]
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[?:?]
at java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2162) ~[?:?]
at com.nukkitx.network.util.Bootstraps.lambda$allOf$0(Bootstraps.java:111) ~[Geyser-Spigot.jar:?]
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:552) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
at io.netty.util.concurrent.DefaultPromise.access$200(DefaultPromise.java:35) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
at io.netty.util.concurrent.DefaultPromise$1.run(DefaultPromise.java:502) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:384) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-all-4.1.68.Final.jar:4.1.68.Final]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
Caused by: io.netty.channel.unix.Errors$NativeIoException: bind(..) failed: Address already in use
INFO19:34:23
[Geyser-Spigot]: Disabling Geyser-Spigot v2.0.3-SNAPSHOT
WARN19:34:23
[Geyser-Spigot]: Failed to load locale asset cache: zip file closed
INFO19:34:23
Running delayed init tasks
Done (10.787s)! For help, type "help"
Timings Reset
WARN19:34:23
[Geyser-Spigot]: Got an error
Console19:34:23
java.lang.IllegalStateException: zip file closed
at java.util.zip.ZipFile.ensureOpen(ZipFile.java:831) ~[?:?]
at java.util.zip.ZipFile.getEntry(ZipFile.java:330) ~[?:?]
at java.util.jar.JarFile.getEntry(JarFile.java:518) ~[?:?]
at java.util.jar.JarFile.getJarEntry(JarFile.java:473) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:163) ~[paper-api-1.18.2-R0.1-SNAPSHOT.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:587) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:108) ~[paper-api-1.18.2-R0.1-SNAPSHOT.jar:?]
at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:103) ~[paper-api-1.18.2-R0.1-SNAPSHOT.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
at org.java_websocket.drafts.Draft.translateHandshakeHttpClient(Draft.java:155) ~[Geyser-Spigot.jar:?]
at org.java_websocket.drafts.Draft.translateHandshakeHttp(Draft.java:100) ~[Geyser-Spigot.jar:?]
at org.java_websocket.drafts.Draft.translateHandshake(Draft.java:285) ~[Geyser-Spigot.jar:?]
at org.java_websocket.WebSocketImpl.decodeHandshake(WebSocketImpl.java:320) ~[Geyser-Spigot.jar:?]
at org.java_websocket.WebSocketImpl.decode(WebSocketImpl.java:219) ~[Geyser-Spigot.jar:?]
at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:506) ~[Geyser-Spigot.jar:?]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
WARN19:34:37
[Geyser-Spigot]: Got an error
Console19:34:37
java.lang.IllegalStateException: zip file closed
at java.util.zip.ZipFile.ensureOpen(ZipFile.java:831) ~[?:?]
at java.util.zip.ZipFile.getEntry(ZipFile.java:330) ~[?:?]
at java.util.jar.JarFile.getEntry(JarFile.java:518) ~[?:?]
at java.util.jar.JarFile.getJarEntry(JarFile.java:473) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:163) ~[paper-api-1.18.2-R0.1-SNAPSHOT.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:587) ~[?:?]
at org.bukkit.plugin.java.PluginClassLoader.loadClass0(PluginClassLoader.java:108) ~[paper-api-1.18.2-R0.1-SNAPSHOT.jar:?]
at org.bukkit.plugin.java.PluginClassLoader.loadClass(PluginClassLoader.java:103) ~[paper-api-1.18.2-R0.1-SNAPSHOT.jar:?]
at java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[?:?]
at org.java_websocket.drafts.Draft.translateHandshakeHttpClient(Draft.java:155) ~[Geyser-Spigot.jar:?]
at org.java_websocket.drafts.Draft.translateHandshakeHttp(Draft.java:100) ~[Geyser-Spigot.jar:?]
at org.java_websocket.drafts.Draft.translateHandshake(Draft.java:285) ~[Geyser-Spigot.jar:?]
at org.java_websocket.WebSocketImpl.decodeHandshake(WebSocketImpl.java:320) ~[Geyser-Spigot.jar:?]
at org.java_websocket.WebSocketImpl.decode(WebSocketImpl.java:219) ~[Geyser-Spigot.jar:?]
at org.java_websocket.client.WebSocketClient.run(WebSocketClient.java:506) ~[Geyser-Spigot.jar:?]
at java.lang.Thread.run(Thread.java:833) ~[?:?]

The relevant part seems to be:

Caused by: io.netty.channel.unix.Errors$NativeIoException: bind(..) failed: Address already in use

But as I am using unique ports for the Minecraft connection, and these instances are both running in Docker, I’m not sure what else could possibly cause this.

I’m at a loss here.

Hopefully someone has some more ideas.

Thanks!

Update: another thing I tried is to disable auto-start of the first instance with Floodgate+Geyser, and then restart ADS. I also tried rebooting the server with auto-start of the first instance disabled. Neither had any effect. I’m struggling to see why this instance is any different from the first instance. I have compared all settings between the two instances, and other that the port numbers, everything other than a few minor game settings are identical.