fix: autogrow input sizing + surface nested error details in upgrade command (#18796)

## Summary

### Fix 1: Autogrow input unclickable when value is empty string
- Fixes the last name input on the Person record show page being
unclickable on regular screens

### Fix 2: Surface nested migration errors in add-missing-system-fields
command
- `AddMissingSystemFieldsToStandardObjectsCommand` calls
`workspaceMigrationRunnerService.run()` directly and was re-throwing
`WorkspaceMigrationRunnerException` without reading its nested `errors`
- Extracted `getNestedErrorMessages()` helper (reused by both
`isUniqueViolationError` and `enrichErrorMessage`)
- Both catch sites now call `enrichErrorMessage()` before re-throwing,
appending nested error details to the message

**Before:**
```
ERROR [UpgradeCommand] Error in workspace ...: Migration action 'create' for 'fieldMetadata' failed
ERROR [UpgradeCommand] undefined
```

**After:**
```
ERROR [UpgradeCommand] Error in workspace ...: Migration action 'create' for 'fieldMetadata' failed (metadata: duplicate key value violates unique constraint "...")
```

## Test plan
- [x] Lint passes
- [x] Typecheck passes
- [x] Verify upgrade command errors now include nested error details
- [x] Verify autogrow input is clickable when value is empty string
This commit is contained in:
Charles Bochet
2026-03-20 13:22:27 +01:00
committed by GitHub
parent 0a6b514898
commit 66be7c3ef4
2 changed files with 42 additions and 12 deletions
@@ -1,4 +1,5 @@
import { InputErrorHelper } from '@/ui/input/components/InputErrorHelper';
import { isNonEmptyString } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
import { InputLabel } from '@/ui/input/components/InputLabel';
import { css } from '@linaria/core';
@@ -459,7 +460,7 @@ const TextInputWithAutoGrowWrapper = forwardRef<
{props.autoGrow ? (
<StyledAutogrowWrapper
sizeVariant={props.sizeVariant}
node={props.value ?? props.placeholder}
node={isNonEmptyString(props.value) ? props.value : props.placeholder}
>
<TextInputComponent
// oxlint-disable-next-line react/jsx-props-no-spreading
@@ -55,27 +55,56 @@ const FIRST_NON_TS_VECTOR_UNIVERSAL_IDENTIFIER =
const DUPLICATE_KEY_MESSAGE = 'duplicate key value violates unique constraint';
const getNestedErrorMessages = (
error: WorkspaceMigrationRunnerException,
): string | undefined => {
const nestedErrors = error.errors;
if (!isDefined(nestedErrors)) {
return undefined;
}
const details = [
nestedErrors.metadata && `metadata: ${nestedErrors.metadata.message}`,
nestedErrors.workspaceSchema &&
`workspaceSchema: ${nestedErrors.workspaceSchema.message}`,
nestedErrors.actionTranspilation &&
`actionTranspilation: ${nestedErrors.actionTranspilation.message}`,
]
.filter(isDefined)
.join('; ');
return details || undefined;
};
const isUniqueViolationError = (error: Error): boolean => {
if (error.message.includes(DUPLICATE_KEY_MESSAGE)) {
return true;
}
if (error instanceof WorkspaceMigrationRunnerException) {
const nestedErrors = [
error.errors?.metadata,
error.errors?.workspaceSchema,
error.errors?.actionTranspilation,
];
const nestedMessages = getNestedErrorMessages(error);
return nestedErrors.some(
(nestedError) =>
nestedError?.message?.includes(DUPLICATE_KEY_MESSAGE) === true,
);
return nestedMessages?.includes(DUPLICATE_KEY_MESSAGE) === true;
}
return false;
};
const enrichErrorMessage = (error: Error): Error => {
if (!(error instanceof WorkspaceMigrationRunnerException)) {
return error;
}
const details = getNestedErrorMessages(error);
if (isDefined(details)) {
error.message = `${error.message} (${details})`;
}
return error;
};
@Command({
name: 'upgrade:1-19:add-missing-system-fields-to-standard-objects',
description:
@@ -123,7 +152,7 @@ export class AddMissingSystemFieldsToStandardObjectsCommand extends ActiveOrSusp
});
} catch (error) {
if (!isUniqueViolationError(error)) {
throw error;
throw enrichErrorMessage(error);
}
this.logger.warn(
@@ -182,7 +211,7 @@ export class AddMissingSystemFieldsToStandardObjectsCommand extends ActiveOrSusp
});
} catch (error) {
if (!isUniqueViolationError(error)) {
throw error;
throw enrichErrorMessage(error);
}
this.logger.warn(