diff --git a/src/server/config.test.ts b/src/server/config.test.ts index 3361e67d..797c3d15 100644 --- a/src/server/config.test.ts +++ b/src/server/config.test.ts @@ -1330,6 +1330,18 @@ describe('validateFieldValue for endpoints', () => { expect(result).toEqual({ success: true }); }); + it('includes the full path for nested array validation errors', () => { + const result = validateFieldValue('endpoints.custom', [ + validEndpoint, + { ...validEndpoint, models: { fetch: true } }, + ]); + + expect(result).toEqual({ + success: false, + error: 'endpoints.custom[1].models.default: Required', + }); + }); + it('gracefully handles unknown deep paths', () => { const result = validateFieldValue('endpoints.custom.0.nonexistent.deep', 'value'); expect(result).toEqual({ success: true }); diff --git a/src/server/config.ts b/src/server/config.ts index d5dbd74c..fa0e6236 100644 --- a/src/server/config.ts +++ b/src/server/config.ts @@ -625,7 +625,14 @@ export function validateFieldValue( } ).safeParse(value); if (!result.success && result.error) { - const messages = result.error.issues.map((i) => i.message); + const messages = result.error.issues.map((issue) => { + const issuePath = issue.path.reduce( + (path, segment) => + typeof segment === 'number' ? `${path}[${segment}]` : `${path}.${segment}`, + fieldPath, + ); + return `${issuePath}: ${issue.message}`; + }); return { success: false, error: messages.join('; ') || 'Validation failed' }; } } @@ -1102,7 +1109,7 @@ export const saveBaseConfigFn = createServerFn({ method: 'POST' }) } } if (errors.length > 0) { - const details = errors.map((e) => `${e.fieldPath}: ${e.error}`).join('; '); + const details = errors.map((e) => e.error).join('; '); throw new Error(`Validation failed — ${details}`); }