Viscord Vonix Mods v5.2.1 Search GitHub
Viscord/Operations/Troubleshooting

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 = true with prefix = "!" will suppress any in-game message starting with !. A player testing with !test sees 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 ServerChatEvent on 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.

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.

  1. 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.
  2. Java version. java -version. A wrong major version explains a whole class of startup failures.
  3. Config, redacted. Paste viscord.toml with 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
  4. 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.
  5. 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.