Skip to content

Improve error message for malformed hook command config#2042

Merged
max-sixty merged 2 commits intomainfrom
config-error
Apr 10, 2026
Merged

Improve error message for malformed hook command config#2042
max-sixty merged 2 commits intomainfrom
config-error

Conversation

@max-sixty
Copy link
Copy Markdown
Owner

The previous error was an opaque "data did not match any variant of untagged enum CommandConfigToml" — users had no way to tell which of the three accepted forms (string, named table, pipeline list) they should use, or which value in their config was the problem.

What changed

Replace #[serde(untagged)] dispatch in CommandConfig/PipelineEntry with custom Visitor impls. Top-level type mismatches now list all three accepted forms inline with a pointer to wt hook --help; nested errors (non-string values inside a map) identify the specific offending value and point at its TOML span. Behavior for valid TOML is unchanged.

Before

TOML parse error at line 1, column 1
  |
1 | post-merge = [
  | ^
data did not match any variant of untagged enum CommandConfigToml

After

Top-level mismatch (post-merge = 42):

invalid type: integer `42`, expected a command in one of these forms:
- a string: "cargo build"
- a named table: { build = "cargo build", test = "cargo test" }
- a pipeline list: ["cargo build", { test = "cargo test" }]
run `wt hook --help` for details

Nested mismatch (post-merge = [{ build = "cargo build", ignore_exit = true }]):

TOML parse error at line 2, column 44
  |
2 |     { build = "cargo build", ignore_exit = true }
  |                                            ^^^^
invalid type: boolean `true`, expected a string

CLAUDE.md

Also adds a "Multiline String Literals" subsection to Code Quality, documenting the canonical style (plain multiline literals, no \-continuation, no concat!()) and when to use raw strings.

Testing

Three new inline-snapshot tests lock in the improved error messages (top-level wrong type, non-string in named table, non-string in pipeline map). Full suite (2962 tests + lints + doctests + doc build) passes.

This was written by Claude Code on behalf of Maximilian Roos

The previous error was an opaque "data did not match any variant of untagged
enum CommandConfigToml" — users had no way to tell which of the three accepted
forms (string, named table, pipeline list) they should use, or which value in
their config was the problem.

Replace the `#[serde(untagged)]` dispatch with a custom Visitor. Top-level
type mismatches now list all three accepted forms inline with a pointer to
`wt hook --help`; nested errors (non-string values inside a map) identify the
specific offending value and point at it in the TOML span. Behavior for valid
TOML is unchanged.

Also add a Multiline String Literals subsection to CLAUDE.md's Code Quality
section, covering the canonical style for multiline constants.

Co-Authored-By: Claude <noreply@anthropic.com>
Add a test for `command = [42]` so the integer-in-pipeline path exercises
PipelineEntryVisitor::expecting (which only fires through serde's error
machinery on type mismatch). Closes a codecov/patch gap on those lines.

Move the message itself into a module-level EXPECTING_PIPELINE_ENTRY
constant — the prior \-line continuation violated the new "Multiline
String Literals" guidance in CLAUDE.md.

Co-Authored-By: Claude <noreply@anthropic.com>
@max-sixty max-sixty merged commit 01e6fe5 into main Apr 10, 2026
25 checks passed
@max-sixty max-sixty deleted the config-error branch April 10, 2026 01:13
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.

2 participants