fix(config): fail fast on malformed or missing config files (#164) - #171
Merged
Conversation
Config loading gave inconsistent guarantees depending on which file you typo'd: `config.json` and `flags.json` logged the parse error, returned 1 and continued with an empty config, while `admins.json` and `triggers.json` raised an uncaught exception. `cli.py` ignored the return code, so a broken `config.json` started the bot with an empty config and the operator saw confusing downstream "Key X not found in config" errors instead of the real cause. Now all four go through one path: - `ConfigFile.load_json()` raises a `ConfigError` carrying the file path and, for a JSON syntax error, the line and column. - `Config.load()` / `SourcemodConfig.Load()` no longer swallow the error and return an int nobody read; both return None. - `cli.py` turns a `ConfigError` during startup (config load or the manager loads inside `TorchlightHandler`) into a `click.ClickException`, so the process aborts with the path + parse error and exit code 1. Live `!reload` is unchanged in spirit: the error surfaces (in chat via the command handler, in the log via the reload callback) and the running config is kept. A `ConfigError` raised from an RCON-reconnect `Init()` is caught by `AsyncClient.Callback` as before; keeping the last-good config across a failed reconnect reload is a separate, larger change. This is a behavior change for server operators: a config typo now refuses to start the bot instead of half-starting. No config schema change, so a valid config needs no edits. Bumps VERSION to 1.8.23. Closes #164 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
4 tasks
Dolly132
approved these changes
Sep 6, 2026
Dolly132
left a comment
Collaborator
There was a problem hiding this comment.
Good for developers, LGTM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Split out of #153 (which deduplicated the loading code but deliberately kept the existing behavior). Makes config loading fail fast and loudly for all four config files instead of the current split where
config.json/flags.jsontolerate malformed JSON and start with an empty config whileadmins.json/triggers.jsonraise an uncaught exception.Changes
Config.py: newConfigErrorexception.ConfigFile.load_json()now catchesFileNotFoundError/OSError/json.JSONDecodeErrorand re-raises aConfigErrorcarrying the file path and, for a syntax error, the line and column.Config.load()andSourcemodConfig.Load()stop swallowing the error and returning anintnobody reads — both now returnNoneand letConfigErrorpropagate.cli.pyconverts aConfigErrorduring startup (the initialconfig.load()and the manager loads insideTorchlightHandler) into aclick.ClickException: the process aborts with the path + parse error and exit code 1, instead of starting empty and emitting confusing downstreamKey X not found in configerrors.Behavior change for operators
A malformed config file now refuses to start the bot instead of half-starting. There is no config schema change — a valid config needs no edits, so this is a patch bump (
1.8.23).Live
!reloadkeeps its spirit: the error surfaces (in chat via the command handler, in the log via the reload callback) and the running config is kept. AConfigErrorraised from an RCON-reconnectInit()is caught byAsyncClient.Callbackexactly as the pre-existingadmins.json/triggers.jsonexceptions were; making a failed reconnect-reload fall back to the last-good config is a larger change and out of scope here.Test plan
ConfigError: <abs path>: invalid JSON on line N, column C (<msg>).ConfigError: <abs path>: config file not found.config/files unchanged: 16 config keys, 1 admin, 21 SM flags, 11 voice triggers (same as refactor(config): share config path resolution and JSON loading via ConfigFile #165's baseline).ruff check,ruff format --diff,mypyclean.Merge order
Part of a batch (#164, #169, #55). Each bumps
VERSIONby one patch in the intended merge order 164 -> 169 -> 55; whichever merges after the first needs a one-lineVERSIONbump on rebase.Closes #164
🤖 Generated with Claude Code