diff --git a/src/cli/tui/components/SecretInput.tsx b/src/cli/tui/components/SecretInput.tsx
index 7794b4aa6..ff6049996 100644
--- a/src/cli/tui/components/SecretInput.tsx
+++ b/src/cli/tui/components/SecretInput.tsx
@@ -38,8 +38,6 @@ export interface SecretInputProps {
}
function validateValue(value: string, schema?: ZodString, customValidation?: CustomValidation): string | undefined {
- if (!value) return undefined;
-
if (customValidation) {
const result = customValidation(value);
if (result !== true) {
@@ -47,6 +45,8 @@ function validateValue(value: string, schema?: ZodString, customValidation?: Cus
}
}
+ if (!value) return undefined;
+
if (schema) {
const parseResult = schema.safeParse(value);
if (!parseResult.success) {
@@ -89,6 +89,11 @@ export function SecretInput({
onSubmit: val => {
const trimmed = val.trim();
if (!trimmed) {
+ const validationError = validateValue(trimmed, schema, customValidation);
+ if (validationError) {
+ setShowError(true);
+ return;
+ }
if (onSkip) {
onSkip();
} else {
diff --git a/src/cli/tui/components/__tests__/SecretInput.test.tsx b/src/cli/tui/components/__tests__/SecretInput.test.tsx
index cf00b0378..d16814f09 100644
--- a/src/cli/tui/components/__tests__/SecretInput.test.tsx
+++ b/src/cli/tui/components/__tests__/SecretInput.test.tsx
@@ -150,6 +150,23 @@ describe('SecretInput', () => {
expect(onCancel).toHaveBeenCalledTimes(1);
});
+ it('shows validation error instead of calling onCancel when customValidation rejects empty value', async () => {
+ const onCancel = vi.fn();
+ const onSubmit = vi.fn();
+ const customValidation = (val: string) => val.trim().length > 0 || 'API key is required';
+ const { lastFrame, stdin } = render(
+
+ );
+
+ await delay();
+ stdin.write(ENTER);
+ await delay();
+
+ expect(onCancel).not.toHaveBeenCalled();
+ expect(onSubmit).not.toHaveBeenCalled();
+ expect(lastFrame()).toContain('API key is required');
+ });
+
it('shows skip hint when onSkip is provided', () => {
const { lastFrame } = render();