Bug description
Real player sessions proposed by the WatchService are consistently rejected
by the Velocity connector with IllegalStateException. The client sees this
as a hang/timeout, not a clean disconnect -- neither a real Java client nor a
synthetic status-ping/login probe ever receives a response once a session is
proposed.
Environment
connect-velocity.jar v0.15.5 (latest as of filing)
- Velocity 4.1.0-SNAPSHOT (git-00759e52-b16) -- a pinned development
build, not a standard/stable Velocity release
- Endpoint claimed via the dashboard, token configured in
token.json,
software type set to Velocity
- Plugins alongside Connect: LuckPerms, Geyser-Velocity + Floodgate,
a small custom hub-command plugin
Observed behavior
Console log, repeated 3 times over a ~7 hour window whenever a real session
was proposed:
Rejected one Connect session proposal (category=IllegalStateException); keeping WatchService active
The WatchService itself stays healthy (Started watching for new player sessions after each), so this is not a connectivity problem -- proposals
are reaching the connector and being actively rejected.
Root cause (found by reading the source, not guessed)
velocity/src/main/java/com/minekube/connect/inject/velocity/VelocityInjector.java,
CurrentVelocityChannelInitializer.initChannel:
ChannelInitializer<Channel> initializer = currentInitializer.get();
if (initializer == null) {
throw new IllegalStateException("Velocity server channel initializer is unavailable");
}
currentInitializer re-reads Velocity's internal cm.serverChannelInitializer
holder via reflection on every tunneled connection (by design, per the
comment above it, so plugins that wrap the holder after Connect starts are
still picked up). For us, that reflective .get() call returns null for
every real session.
Suspected cause
This network is pinned to a Velocity SNAPSHOT build
(4.1.0-SNAPSHOT git-00759e52-b16), not a standard release. Connect's
Velocity integration works entirely through reflection into
ConnectionManager's private fields (cm, serverChannelInitializer,
workerGroup, SERVER_WRITE_MARK) -- there is no supported API for this.
It's plausible this particular build's internal structure/timing around
serverChannelInitializer differs enough from what the reflection code
expects to produce a null read at connection time, even though the same
reflection succeeds once at inject() time (no error is logged there, and
the "channel initializer has been replaced" log line confirms the initial
swap succeeds).
Not confirmed against Velocity's source for this exact SNAPSHOT commit --
flagging the correlation since it's the one thing about our setup that
isn't a standard release build.
Isolation work done before filing
Ruled out before concluding this is a Velocity-build issue rather than a
config mistake on our end:
- Not a Geyser/Floodgate conflict: removed both entirely, restarted with
a bare Velocity + LuckPerms + Connect stack, retested against the same
endpoint -- identical failure.
- Not an unclaimed-endpoint limitation: endpoint was claimed via the
dashboard (app.minekube.com), software type set to Velocity, token
reset and deployed to token.json -- identical failure, endpoint still
shows "Inactive" in the dashboard.
- Not a network/firewall problem: outbound HTTPS to
watch-connect.minekube.net returns a real response (not a timeout); DNS
for the assigned *.play.minekube.net resolves to a real anycast IP; raw
TCP connects immediately.
- Not a wrong-plugin-binary issue: the jar downloaded fresh from the
dashboard's Velocity-specific download link is byte-identical (SHA256) to
the one already installed from the GitHub release.
Expected behavior
Either the reflection path should be robust across Velocity builds (with a
clear error identifying why the holder is null, e.g. build/version
mismatch), or Connect should document which Velocity builds are supported so
this class of failure is diagnosable without reading the plugin's own
source.
Happy to help
This network's operator is willing to test a patched build, provide more
logs, or answer questions -- this was reproduced consistently and isolated
carefully rather than a one-off report.
Bug description
Real player sessions proposed by the WatchService are consistently rejected
by the Velocity connector with
IllegalStateException. The client sees thisas a hang/timeout, not a clean disconnect -- neither a real Java client nor a
synthetic status-ping/login probe ever receives a response once a session is
proposed.
Environment
connect-velocity.jarv0.15.5 (latest as of filing)build, not a standard/stable Velocity release
token.json,software type set to Velocity
a small custom hub-command plugin
Observed behavior
Console log, repeated 3 times over a ~7 hour window whenever a real session
was proposed:
The WatchService itself stays healthy (
Started watching for new player sessionsafter each), so this is not a connectivity problem -- proposalsare reaching the connector and being actively rejected.
Root cause (found by reading the source, not guessed)
velocity/src/main/java/com/minekube/connect/inject/velocity/VelocityInjector.java,CurrentVelocityChannelInitializer.initChannel:currentInitializerre-reads Velocity's internalcm.serverChannelInitializerholder via reflection on every tunneled connection (by design, per the
comment above it, so plugins that wrap the holder after Connect starts are
still picked up). For us, that reflective
.get()call returnsnullforevery real session.
Suspected cause
This network is pinned to a Velocity SNAPSHOT build
(
4.1.0-SNAPSHOT git-00759e52-b16), not a standard release. Connect'sVelocity integration works entirely through reflection into
ConnectionManager's private fields (cm,serverChannelInitializer,workerGroup,SERVER_WRITE_MARK) -- there is no supported API for this.It's plausible this particular build's internal structure/timing around
serverChannelInitializerdiffers enough from what the reflection codeexpects to produce a
nullread at connection time, even though the samereflection succeeds once at
inject()time (no error is logged there, andthe "channel initializer has been replaced" log line confirms the initial
swap succeeds).
Not confirmed against Velocity's source for this exact SNAPSHOT commit --
flagging the correlation since it's the one thing about our setup that
isn't a standard release build.
Isolation work done before filing
Ruled out before concluding this is a Velocity-build issue rather than a
config mistake on our end:
a bare Velocity + LuckPerms + Connect stack, retested against the same
endpoint -- identical failure.
dashboard (
app.minekube.com), software type set to Velocity, tokenreset and deployed to
token.json-- identical failure, endpoint stillshows "Inactive" in the dashboard.
watch-connect.minekube.netreturns a real response (not a timeout); DNSfor the assigned
*.play.minekube.netresolves to a real anycast IP; rawTCP connects immediately.
dashboard's Velocity-specific download link is byte-identical (SHA256) to
the one already installed from the GitHub release.
Expected behavior
Either the reflection path should be robust across Velocity builds (with a
clear error identifying why the holder is null, e.g. build/version
mismatch), or Connect should document which Velocity builds are supported so
this class of failure is diagnosable without reading the plugin's own
source.
Happy to help
This network's operator is willing to test a patched build, provide more
logs, or answer questions -- this was reproduced consistently and isolated
carefully rather than a one-off report.