FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(web): show nested Zod errors in FormMessage by nkabardin · Pull Request #16317 · langfuse/langfuse · GitHub

fix(web): show nested Zod errors in FormMessage - #16317

Merged
nkabardin merged 10 commits into
mainfrom
lfe-15322-formmessage-nested-errors
Aug 26, 2026
Merged

nkabardin merged 10 commits into
mainfrom
lfe-15322-formmessage-nested-errors

Conversation

nkabardin commented Aug 19, 2026
edited by github-actions Bot
Loading

Copy link
Copy Markdown
Contributor

🟡 Live preview: pr-16317.preview.langfuse.com

What does this PR do?

When an array field has both item-level and array-level Zod errors, react-hook-form stores the array message on root and leaves error.message undefined. FormMessage only read error.message, so the form blocked submit with no visible text.

This walks message → root → nested children so the shared primitive shows those errors. The eval template category workaround is now a normal FormMessage. Widget save-reason copy also prefers metrics.root.

Companion toast work is already in #16313.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Mandatory Tasks

  • Make sure you have self-reviewed the code.

Checklist

  • Tests: pnpm --filter web run test-client src/components/ui/form.clienttest.tsx and src/features/widgets/components/widgetFormSchema.clienttest.ts
  • Typecheck: CI web#typecheck failed on this branch's FormMessage tests (categories.root / categories.config are not RHF FieldPath keys). Tests now set those nested paths through a typed helper. Not a main failure.
  • Lint: pnpm --filter web run lint via pre-commit turbo lint
  • Impacted package: web

Test this

Preview: https://pr-16317.preview.langfuse.com

  1. Open Evaluators → create/edit a categorical template.
  2. Leave a category empty and add fewer than two categories, then save.
  3. Expect inline red text under categories, not a silent save.

Data: demo project is enough.
Sandbox: http://localhost:3000 same path.

Slack Thread

  

Greptile Summary

This PR updates shared form error rendering to discover Zod/react-hook-form messages stored under root or nested child paths, replacing the evaluator-specific workaround and extending widget save-reason extraction.

  • Adds recursive nested error-message selection to FormMessage.
  • Uses the shared primitive for categorical evaluator errors.
  • Prioritizes metrics.root.message in widget validation feedback.
  • Adds focused client tests for nested, root, array-level, union-path, and empty errors.

Confidence Score: 5/5

The PR appears safe to merge, with the nested validation behavior covered by focused tests and no actionable defects identified.

The shared renderer preserves direct-message and child fallback behavior while adding explicit root handling, and the evaluator and widget consumers consistently adopt the intended error priority.

Reviews (1): Last reviewed commit: "fix(web): show nested Zod errors in Form..." | Re-trigger Greptile

Array-level and item errors from Zod 4 leave error.message undefined, so the
shared FormMessage rendered nothing. Walk root and nested field errors, and
drop the eval-template workaround that duplicated that logic.

Co-authored-by: Nikita Kabardin <nikita@kabardin.com>
dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. bug Something isn't working ui labels Aug 19, 2026

Copy link
Copy Markdown
Contributor

@claude review

cursor Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Doubt this: getFieldErrorMessage prefers root then the first nested child, so a parent FormMessage on an array can show an item error when there is no array-level message (eval template now has both a parent FormMessage and per-item ones). Also type is treated as a nested error only when it is an object, which is a heuristic for Zod union paths vs RHF metadata.

github-actions Bot commented Aug 19, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

🟢 AWS preview image pushed

Argo CD is rolling it out — the environment is usually ready within a
few minutes of this comment.

URL: https://pr-16317.preview.langfuse.com (signs you in automatically; opt out with /auth/sign-in?autoSignIn=false)
Login: demo@langfuse.com / password
API keys: pk-lf-1234567890 / sk-lf-1234567890
Commit: b8d7101

URL not loading / 404? Full debug guide — deploy allowlist,
sleeping preview, pod status, ClickHouse:
https://github.com/langfuse/langfuse/blob/main/.agents/skills/langfuse-previews/SKILL.md#debug-a-preview

Logs (needs preview-cluster kubectl access):

kubectl -n langfuse-pr-16317 logs -f deploy/langfuse-pr-16317-web      # web
kubectl -n langfuse-pr-16317 logs -f deploy/langfuse-pr-16317-worker   # worker

Add --previous for a crashed container, --tail=200 to limit, or
kubectl -n langfuse-pr-16317 get pods to inspect status.

Synthetic preview data only. Never add production data to public accounts.

nkabardin and others added 2 commits August 20, 2026 17:59
Parent FormMessage on categories was repeating per-item empty-value errors.
Only render it when the array itself has a message or root message.

cursor Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

What to doubt in review

  • I gated the eval-template parent FormMessage so it only renders for categories.message / categories.root.message. Array-level "too few categories" still shows at the bottom; empty item values stay on the per-item field. Tell me if that hides a real array error.
  • getFieldErrorMessage still treats type as nested only when it is an object, which is a heuristic for Zod union paths vs react-hook-form metadata.

Copy link
Copy Markdown
Contributor Author

@claude review

claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

LGTM with one nit. The previously flagged categories duplicate-warning issue in template-form.tsx has been fixed by gating the parent FormMessage to array-level errors only. A new inline comment flags the identical duplicate-warning pattern in the untouched variable-mapping-card.tsx (sibling call site with the same bare array-level FormMessage) — purely cosmetic and not a submit-blocking issue, so it doesn't need to hold up this PR.

Extended reasoning...

Overview

This PR changes how FormMessage (web/src/components/ui/form.tsx) resolves an error message from a react-hook-form/Zod error object: instead of reading only error.message, it now recursively walks message → root → nested children. It updates template-form.tsx to use the shared primitive instead of a local workaround, and updates WidgetForm.tsx/widgetFormSchema.ts to also check metrics.root.message when deriving the save-blocked reason text. All changes are confined to client-side form-rendering/UX code with client tests added for the new recursive behavior.

Security risks

None. This is purely presentational error-message rendering; no data handling, auth, or trust-boundary code is touched.

Level of scrutiny

Low-to-moderate. This is a UI-only bug fix with narrow blast radius (form error display), reasonable test coverage (form.clienttest.tsx, widgetFormSchema.clienttest.ts), and the riskiest part — the new generic recursive fallback in a shared primitive — was specifically probed for regressions across its various callers, since a shared, generic change like this can surface latent duplicate-render issues at other call sites that weren't touched by the PR itself (as it did here for variable-mapping-card.tsx).

Other factors

The author (via a follow-up agent commit) already addressed my prior review comment about the template-form.tsx categories duplicate by gating the parent FormMessage. The newly found duplicate-warning pattern in variable-mapping-card.tsx is structurally identical but purely cosmetic (validation/submit-blocking behavior is unaffected), so it doesn't rise to a merge-blocking severity, though it's worth the author's attention as a quick follow-up.

Copy link
Copy Markdown
Contributor

🧹 Preview environment torn down after 2 days of inactivity (last update 2026-08-20T16:25:14Z). Re-add the preview label to redeploy.

github-actions Bot removed the preview label Aug 23, 2026
Parent FormMessage on eval variable mappings was repeating per-row
JsonPath warnings. Gate array-level FormMessages with a shared helper.

cursor Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

What to doubt in review

  • Parent FormMessages on categories and mapping now render only for message/root. Per-item JsonPath and empty-category errors stay on the row. Tell me if an array-level error can live somewhere else.
  • getFieldErrorMessage still treats type as nested only when it is an object, which is a heuristic for Zod union paths vs react-hook-form metadata.

nkabardin enabled auto-merge August 26, 2026 09:17
dosubot Bot added the auto-merge This PR is set to be merged label Aug 26, 2026
nkabardin added this pull request to the merge queue Aug 26, 2026
Merged via the queue into main with commit 7548b2a Aug 26, 2026
45 checks passed
nkabardin deleted the lfe-15322-formmessage-nested-errors branch August 26, 2026 10:12
dosubot Bot removed the auto-merge This PR is set to be merged label Aug 26, 2026
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

Labels

bug Something isn't working preview size:L This PR changes 100-499 lines, ignoring generated files. ui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants


Back | FazBrowse Home | New Git URL