From c9d0d079b38cfbc298c094a5b37b2af9b2dde034 Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Tue, 6 Jan 2026 11:29:01 +0100 Subject: [PATCH] fix(frontend): show validation errors when agent type form fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When form validation fails (e.g., personality_prompt is empty), the form would silently not submit. Now it shows a toast with the first error and navigates to the tab containing the error field. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../src/components/agents/AgentTypeForm.tsx | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/agents/AgentTypeForm.tsx b/frontend/src/components/agents/AgentTypeForm.tsx index 6a40677..052d861 100644 --- a/frontend/src/components/agents/AgentTypeForm.tsx +++ b/frontend/src/components/agents/AgentTypeForm.tsx @@ -7,9 +7,10 @@ 'use client'; -import { useEffect, useState } from 'react'; -import { useForm, Controller } from 'react-hook-form'; +import { useEffect, useState, useCallback } from 'react'; +import { useForm, Controller, type FieldErrors } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; +import { toast } from 'sonner'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; @@ -89,6 +90,30 @@ export function AgentTypeForm({ formState: { errors }, } = form; + // Handle form validation errors - show toast with first error + const handleFormError = useCallback((formErrors: FieldErrors) => { + // Find the first error and show it + const firstErrorKey = Object.keys(formErrors)[0] as keyof AgentTypeCreateFormValues; + if (firstErrorKey) { + const error = formErrors[firstErrorKey]; + const message = error && 'message' in error ? error.message : 'Validation error'; + toast.error('Please fix form errors', { + description: `${String(firstErrorKey)}: ${message}`, + }); + + // Navigate to the tab containing the error + if (['name', 'slug', 'description', 'expertise', 'is_active'].includes(firstErrorKey)) { + setActiveTab('basic'); + } else if (['primary_model', 'fallback_models', 'model_params'].includes(firstErrorKey)) { + setActiveTab('model'); + } else if (['mcp_servers', 'tool_permissions'].includes(firstErrorKey)) { + setActiveTab('permissions'); + } else if (firstErrorKey === 'personality_prompt') { + setActiveTab('personality'); + } + } + }, []); + const watchName = watch('name'); /* istanbul ignore next -- defensive fallback, expertise always has default */ const watchExpertise = watch('expertise') || []; @@ -133,7 +158,7 @@ export function AgentTypeForm({ }; return ( -
+ {/* Header */}