Skip to content

fix(config): fail fast on malformed or missing config files (#164) - #171

Merged
Rushaway merged 1 commit into
masterfrom
fix/164-config-loading-error-handling
Sep 6, 2026
Merged

fix(config): fail fast on malformed or missing config files (#164)#171
Rushaway merged 1 commit into
masterfrom
fix/164-config-loading-error-handling

Conversation

@Rushaway

@Rushaway Rushaway commented Sep 6, 2026

Copy link
Copy Markdown
Member

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.json tolerate malformed JSON and start with an empty config while admins.json / triggers.json raise an uncaught exception.

Changes

  • Config.py: new ConfigError exception. ConfigFile.load_json() now catches FileNotFoundError / OSError / json.JSONDecodeError and re-raises a ConfigError carrying the file path and, for a syntax error, the line and column.
  • Config.load() and SourcemodConfig.Load() stop swallowing the error and returning an int nobody reads — both now return None and let ConfigError propagate.
  • cli.py converts a ConfigError during startup (the initial config.load() and the manager loads inside TorchlightHandler) into a click.ClickException: the process aborts with the path + parse error and exit code 1, instead of starting empty and emitting confusing downstream Key X not found in config errors.

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 !reload keeps its 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 exactly as the pre-existing admins.json / triggers.json exceptions were; making a failed reconnect-reload fall back to the last-good config is a larger change and out of scope here.

Test plan

  • Fed each loader malformed JSON -> ConfigError: <abs path>: invalid JSON on line N, column C (<msg>).
  • Missing file -> ConfigError: <abs path>: config file not found.
  • All four load the real 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, mypy clean.

Merge order

Part of a batch (#164, #169, #55). Each bumps VERSION by one patch in the intended merge order 164 -> 169 -> 55; whichever merges after the first needs a one-line VERSION bump on rebase.

Closes #164

🤖 Generated with Claude Code

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>

@Dolly132 Dolly132 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good for developers, LGTM

@Rushaway
Rushaway merged commit eb19b00 into master Sep 6, 2026
3 checks passed
@Rushaway
Rushaway deleted the fix/164-config-loading-error-handling branch September 6, 2026 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Config loading error handling is inconsistent: two files tolerate malformed JSON, two crash

2 participants