Troubleshooting#
Each entry below is a real failure mode: what you see, why it happens, and what fixes it.
Nothing happens on startup#
Symptom. The server starts, Viscord loads, and no bot ever appears online. The
log shows [Viscord] Disabled in config.
Cause. general.enabled is false. That is the shipped default, and it is also
what a fresh viscord.toml contains on first boot.
Fix. Set general.enabled = true and run /viscord reload as an op-4
operator, or restart. If you have just installed and never edited the file, this
is the expected state — first boot exists only to produce the config.
You can confirm the state from the game side with /viscord status, which prints
Enabled: No next to Status: Stopped.
Config file not generating#
Symptom. The server has been started but config/viscord/viscord.toml does
not exist.
Cause. The server process could not create the directory. Common reasons: the
server runs as a user without write access to config/, config/viscord exists
as a file rather than a directory, or a container mounts config/ read-only.
Fix. Check the log for the resolved path — Viscord logs it on initialise:
[Viscord] Config directory: /path/to/server/config/viscord
[Viscord] Config file path: /path/to/server/config/viscord/viscord.toml
Create the directory yourself with the right owner and restart:
mkdir -p /path/to/server/config/viscord
chown <server-user>:<server-group> /path/to/server/config/viscord
If Viscord cannot write the file it throws
NightConfig did not materialize <path>; that message in the log is the
confirmation that this is a permissions problem rather than a mod problem.
Discord to Minecraft is silent#
Symptom. In-game chat reaches Discord, but nothing typed in Discord appears in game. No errors in the log.
This has four common causes. Check them in this order — each is cheaper than the next.
1. Message Content Intent is off. This is the most frequent cause by a wide margin. The gateway connects, the bot shows online, and every message arrives with an empty body. Enable Message Content Intent under Bot → Privileged Gateway Intents in the Discord developer portal, then restart the bot (a reload is enough, because it reconnects).
2. Channel permissions. The bot needs View Channel and Read Message History in the channel it is supposed to read. Without Read Message History it will not see message content reliably. Check the channel-level override, not just the role.
3. Channel ID mismatch. discord.channel_id must be the numeric ID, not the
channel name. Any message from a channel not in the configured list is dropped
before processing, with no log line at default verbosity. Set general.debug and
watch for whether the message is seen at all.
4. Filters are eating it. In a shared channel, filters.ignore_bots and
filters.ignore_webhooks will drop another server's traffic unless its ID is in
filters.trusted_bot_ids. And if the author name happens to start with your
server.prefix, the self-origin check drops it unconditionally — an ordinary user
typing [MC] hello is safe, because that check only applies to bots and webhooks.
Minecraft to Discord is silent#
Symptom. Discord to Minecraft works fine. In-game chat never appears in Discord.
Cause. discord.webhook_url is empty. Outbound chat is sent only through
the webhook; there is no bot-API fallback on the Discord side. The bot can read the
channel perfectly and still never post a chat message.
Fix. Create a webhook in the channel (Channel settings → Integrations
→ Webhooks) and put its URL in discord.webhook_url, then reload.
Two adjacent causes worth ruling out:
filters.chat.enabled = truewithprefix = "!"will suppress any in-game message starting with!. A player testing with!testsees nothing.- The player is not actually chatting — a message sent through a plugin that
bypasses the server chat packet may not be captured. Viscord hooks the chat
packet on Fabric and
ServerChatEventon NeoForge/Forge.
Fluxer never appears#
Symptom. With platform = "fluxer", nothing connects and isRunning() stays
false.
Cause and fix, in order of likelihood:
Wrong platform value. general.platform must be fluxer, lowercase-tolerant
but not Fluxer with a trailing space. Viscord compares case-insensitively but a
typo like flux falls through to the Discord branch.
Token or channel left at the placeholder. The Fluxer client validates against
YOUR_FLUXER_BOT_TOKEN and YOUR_FLUXER_CHANNEL_ID by literal string, so an
unedited config produces:
[Fluxer] Bot token not configured! Set fluxer.bot_token in config.
Auth rejected by the gateway. The client logs
[Fluxer Bot] Authentication failed (4004). Token is invalid. Not reconnecting.
and stops. Fix the token and reload — an explicit disconnect or a fatal close
code clears the token and halts reconnection, so a reload is required.
Gateway unreachable. The log stops at
[Fluxer Bot] Connecting to gateway.... Check outbound WSS to
gateway.fluxer.app on 443. No inbound port is involved, so a failure here is
egress, DNS, or a proxy.
Event channel missing. Event embeds need fluxer.event_channel_id or a
fallback to fluxer.channel_id, and the bot must be able to post there. The log
shows Cannot send event embed — no event channel configured when neither is set.
A tridirectional-specific trap. When general.tridirectional.enabled = true,
Fluxer initialises first and a failure sets running = false and returns before
Discord is ever connected. A broken Fluxer token therefore takes Discord down with
it. If a tridirectional setup is entirely dead, check Fluxer before Discord.
Chat appears as the bot instead of the player#
Symptom. Messages arrive in Discord, but every line shows the bot's name and avatar rather than the player's.
Cause. On Discord, this means discord.webhook_url is empty. Outbound chat is
never sent through the bot API, so an empty webhook means no chat at all — if you
are seeing bot-authored lines, you are looking at event embeds, not chat.
On Fluxer, this is the documented fallback. Without fluxer.webhook_url,
Minecraft chat is posted through the bot API as **name**: text. The name is
preserved in the text; the identity is not.
Fix. Configure the webhook for the platform in question. On Fluxer this is optional but recommended; on Discord it is required.
A related symptom: chat appears under the right name but with a generic avatar.
That is server.avatar_url pointing at something that does not resolve for that
player. The default Minotar template works for premium accounts; a cracked or
offline-mode server usually needs a different avatar source.
Cross-server events disappear#
Symptom. Two servers share an event channel. Each posts its own joins and leaves, but neither shows the other's.
Cause. filters.trusted_bot_ids does not contain the other server's bot or
webhook ID. With filters.ignore_bots = true (the default), every automated
author is dropped.
Fix. Add the peer IDs to each server's list, comma-separated:
[filters]
trusted_bot_ids = "222222222222222222,333333333333333333"
Get IDs with Developer Mode enabled: right-click the bot → Copy User ID, or right-click a webhook message → Copy Message ID is not what you want — use the bot's user ID or the webhook's ID from channel integrations.
If the IDs are right and events still do not appear, check
filters.show_other_server_events. With it false, anything arriving on the event
channel is dropped before the author check runs.
Display names look wrong#
Symptom. A Discord user appears in game under a name you did not expect — either a nickname rather than their account name, or vice versa.
Cause. messages.use_display_name controls the resolution chain. true (the
default) resolves server nickname, then global display name, then account name.
false uses the plain account name only.
Fix. Set it to false for stable, privacy-friendly names. Note that this also changes the name written into a link binding, because the link flow records the author's display name at redemption time.
A different display problem: the name in Discord shows as [Discord]name with no
space. That is the Fluxer → Discord bridge path, which sends the webhook name
as "[Fluxer]" + username. It is cosmetic and fixed in the payload, not in
config.
/link stops responding#
Symptom. A player types /link 123456 in Discord and nothing happens. No
reply, no error, no reaction.
Cause. The legacy text trigger is silent when rate limited. This is deliberate: replying would let an attacker measure the limit window and pace their attempts around it, and would spam the channel during an attack.
Fix. Wait out the window. The default is 3 attempts per user per minute and 30
per channel. To confirm it is a rate limit rather than a broken bot, set
general.debug = true, which emits one line naming the bucket:
[Viscord] Rate limit (per-user): 3 attempts/min reached for LINK by <id>
Prefer the native /link code command: it replies
Too many link attempts. Please wait before trying again. instead of staying
silent.
Account linking fails#
| What you see | Cause | Fix |
|---|---|---|
Account linking is disabled. |
account_linking.enabled = false |
Enable it and reload |
Discord bot is not connected. |
Platform not running | Fix the platform first — see the sections above |
Already linked to <name> |
This UUID has a binding | Unlink first |
Invalid or expired link code! |
Code aged out or was already used | Generate a new one |
This Discord account is already linked to Minecraft player <x> |
That Discord ID is bound elsewhere | Unlink the other account, or use a different Discord account |
This Minecraft account is already linked to Discord user <y> |
The UUID gained a binding between generation and redemption | Unlink, then redo the flow |
Codes are single-use and are burned on a wrong guess. A player who mistypes has to generate a new code; there is no retry on the same code.
Pending codes are in-memory only. A restart between generating and redeeming
invalidates every outstanding code, and the player will see
Invalid or expired link code! for a code that was valid a minute earlier.
Reload fails#
Symptom. /viscord reload prints Failed to reload: <message>.
Cause. Usually a malformed viscord.toml. TOML is strict about quotes, table
headers, and trailing commas; a hand edit that breaks the syntax throws during
parse.
Fix. Validate the file before reloading:
python3 -c "import tomllib,sys; tomllib.load(open('config/viscord/viscord.toml','rb'))" && echo OK
Then check the log for the stack trace — the failure message carries the exception
text, and the full trace is logged at error level under [Viscord] Reload failed.
A second cause: the reload succeeded but the new config has general.enabled =
false, in which case you get the informational Viscord is disabled in config.
rather than a failure. That is a success with an inactive result.
If you see no response at all within a few seconds, the reload threw before it reached the feedback line. The log is the only reliable signal in that case.
Shutdown hangs or the offline message is missing#
Symptom. Stopping the server takes noticeably longer than usual, or the "Server Offline" embed never appears.
Cause and expectation. Viscord deliberately delays the Discord disconnect by 2500 ms and then waits up to 3 seconds for the offline embed to be delivered. A stop taking five or six seconds longer than a bare server is the designed behaviour, not a hang.
If it is worse than that:
- A missing embed with a normal-length stop means the HTTP request timed out. The timeout is caught and logged, and shutdown continues.
- A genuinely long stop with
platform = "both"or tridirectional means two platform shutdowns are being sequenced. Check for repeated reconnect attempts in the log from a Fluxer client that is retrying during shutdown. - If
general.enabled = false, shutdown is immediate. A delay on a disabled install is not Viscord.
& corruption in URLs#
Symptom. A URL posted in game arrives in Discord with § where & should be,
e.g. ?a=1§b=2.
Cause. A legacy build replaced every & with §. Current code only converts
& when it is followed by a valid Minecraft formatting character or # (hex), so
&b in a query string is still ambiguous — b is a valid colour code.
Fix. Upgrade if you are on an old build. If you are current, the deliberate
escape is unavoidable for a letter that is also a colour code: &b, &a, &c,
&d, &e, &f, &0–&9, &k, &l, &m, &n, &o, &r. URL-encode the
ampersand as %26 when you need it to survive:
https://example.com/page?a=1%26b=2
Non-op players cannot use the toggles#
Symptom. A regular player runs /discord messages and gets an unknown-command
or permission error.
Cause. On current builds this should not happen: the /discord tree is
registered at op level 0, and only /viscord reload and /viscord status require
op 4.
Fix. Confirm you are not on a build older than 4.1.5. Earlier versions
inherited the op-4 predicate from a sibling /viscord registration through
Brigadier's tree-merge behaviour, which made the whole /discord tree
operator-only. If you are current and a player still cannot use it, check whether a
permissions plugin is overriding the command node — Viscord registers at level 0,
but a plugin can still deny it.
Note that /vonix is a genuine exception: its root requires op 4, so a non-op gets
no response from it at all. That is correct and that tree only prints deprecation
notices.
Collecting a diagnostic bundle#
When you need help, gather these five things. Do not skip the redaction step.
- Version and cell. The jar filename carries both:
viscord-1.21.1-neoforge-5.2.1.jar. Include the Minecraft version, the loader, and the loader version. - Java version.
java -version. A wrong major version explains a whole class of startup failures. - Config, redacted. Paste
viscord.tomlwith these values replaced by obvious placeholders: -discord.bot_token-fluxer.bot_token-discord.webhook_url— replace the whole thing, not just the token segment -fluxer.webhook_url - Debug logs. Set
general.debug = true, reproduce the problem, and grab the lines containing[Viscord],[Discord], or[Fluxer]. Include the surrounding stack trace if there is one. - What you already tried. Which mode (
discord,fluxer,both, tridirectional), and whether the problem is one direction or both.
What not to include: the unredacted config, a bot token "just to test", or a screenshot of the developer portal's bot page.
For a first pass, /viscord status gives you the running state, the configured
platform, and the enabled flag in one command. In Discord, /status gives the
connection state and player count if you are an administrator.