Hive Hive
Sign in

fix(mcp): keep changeset errors from crashing on non-binary opts

GitHub issue · Closed

Metadata
Source
tuist/hive #25
Updated
Jun 24, 2026
Domains
Hive
Details

Summary

  • Hive.MCP.Tool.changeset_errors/1 interpolates error options into the message via String.replace(msg, "%{key}", to_string(value)). String.replace/3 evaluates its third arg eagerly, so to_string/1 is called on every opt regardless of whether its placeholder appears in the message.
  • Ecto.Enum cast errors include type: {:parameterized, {Ecto.Enum, %{...}}} in their opts. Tuples don’t implement String.Chars, so the eager to_string/1 raises Protocol.UndefinedError, which surfaces to the MCP transport as a generic 500. Reproducer: call update_spec with a status value not in the enum (e.g. "accepted" against the current [:draft, :proposed, :approved, :paused, :rejected, :in_progress, :shipped, :archived]).
  • Switch to the function form of String.replace/3 so options are only stringified when the placeholder is actually present. Add a stringify_option/1 helper that handles strings, atoms, and numbers cleanly, and falls back to inspect/1 for any other shape so future Ecto error opts can’t regress this.

Test plan

  • mix test test/hive/mcp/tool_test.exs — new test casts a bogus value into a parameterized Ecto.Enum; previously crashed inside traverse_errors with Protocol.UndefinedError, now returns %{status: ["is invalid"]}.
  • mix test — full suite (306 tests, 0 failures).
  • mix compile --warnings-as-errors, mix format, mix credo --strict on the touched files.

🤖 Generated with Claude Code

Comments

No GitHub comments yet.