Skip to content

Null equivalence - remove feature flag#16222

Merged
charlesBochet merged 1 commit intomainfrom
ej/remove-ff
Dec 1, 2025
Merged

Null equivalence - remove feature flag#16222
charlesBochet merged 1 commit intomainfrom
ej/remove-ff

Conversation

@etiennejouan
Copy link
Copy Markdown
Contributor

No description provided.

Comment on lines 248 to 258

return transformFullNameField(validatedValue, isNullEquivalenceEnabled);
return transformFullNameField(validatedValue);
}

case FieldMetadataType.ADDRESS: {
const validatedValue = validateAddressFieldOrThrow(value, key);

return transformAddressField(validatedValue, isNullEquivalenceEnabled);
return transformAddressField(validatedValue);
}
case FieldMetadataType.CURRENCY: {
const validatedValue = validateCurrencyFieldOrThrow(value, key);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: transformEmailsValue lacks null equivalence logic, preventing conversion of empty email values to null.
Severity: CRITICAL | Confidence: High

🔍 Detailed Analysis

The transformEmailsValue function fails to convert null-equivalent email values (e.g., empty strings or objects) to null. This occurs because its implementation was not updated to include null equivalence logic, despite the call site in data-arg-processor.ts being modified to remove the isNullEquivalenceEnabled parameter. This omission leads to inconsistent data handling for email fields, as they will retain their null-equivalent values instead of being normalized to null, breaking the intended behavior of the pull request.

💡 Suggested Fix

Implement null equivalence logic within transformEmailsValue, potentially by calling a new isNullEquivalentEmailFieldValue utility function, to ensure empty email values are correctly converted to null.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location:
packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/data-arg.processor.ts#L241-L258

Potential issue: The `transformEmailsValue` function fails to convert null-equivalent
email values (e.g., empty strings or objects) to `null`. This occurs because its
implementation was not updated to include null equivalence logic, despite the call site
in `data-arg-processor.ts` being modified to remove the `isNullEquivalenceEnabled`
parameter. This omission leads to inconsistent data handling for email fields, as they
will retain their null-equivalent values instead of being normalized to `null`, breaking
the intended behavior of the pull request.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 4609673

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Dec 1, 2025

📊 API Changes Report

GraphQL Schema Changes

GraphQL Schema Changes

[log]
Detected the following changes (1) between schemas:

[log] ✖ Enum value IS_NULL_EQUIVALENCE_ENABLED was removed from enum FeatureFlagKey
[error] Detected 1 breaking change
⚠️ Breaking changes or errors detected in GraphQL schema

[log] 
Detected the following changes (1) between schemas:

[log] ✖  Enum value IS_NULL_EQUIVALENCE_ENABLED was removed from enum FeatureFlagKey
[error] Detected 1 breaking change
Error generating diff

GraphQL Metadata Schema Changes

GraphQL Metadata Schema Changes

[log]
Detected the following changes (1) between schemas:

[log] ✖ Enum value IS_NULL_EQUIVALENCE_ENABLED was removed from enum FeatureFlagKey
[error] Detected 1 breaking change
⚠️ Breaking changes or errors detected in GraphQL metadata schema

[log] 
Detected the following changes (1) between schemas:

[log] ✖  Enum value IS_NULL_EQUIVALENCE_ENABLED was removed from enum FeatureFlagKey
[error] Detected 1 breaking change
Error generating diff

⚠️ Please review these API changes carefully before merging.

⚠️ Breaking Change Protocol

Breaking changes detected but PR title does not contain "breaking" - CI will pass but action needed.

🔄 Options:

  1. If this IS a breaking change: Add "breaking" to your PR title and add BREAKING CHANGE: to your commit message
  2. If this is NOT a breaking change: The API diff tool may have false positives - please review carefully

For breaking changes, add to commit message:

feat: add new API endpoint

BREAKING CHANGE: removed deprecated field from User schema

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Dec 1, 2025

Greptile Overview

Greptile Summary

This PR removes the IS_NULL_EQUIVALENCE_ENABLED feature flag from across the Twenty codebase, makingnull equivalence handling the permanent default behavior. The null equivalence feature allows treating empty strings, empty arrays, and empty objects as equivalent to null values in database operations and data transformations.

The changes span multiple areas: removing the feature flag from enums, removing it from default workspace feature flags, removing feature flag parameters from data transformation utilities (text fields, arrays, currency, full names, actors, emails, raw JSON, and addresses), updating test files to match the new function signatures, and cleaning up related migration commands. Additionally, a utility file compute-unique-index-where-clause.util.ts was completely removed as it was specifically designed for null equivalence handling and is no longer needed.

This represents the final step in graduating the null equivalence feature from experimental/feature-flagged status to permanent functionality, indicating the feature has been thoroughly tested and validated in production environments.

Important Files Changed

Filename Score Overview
packages/twenty-server/src/engine/metadata-modules/index-metadata/utils/compute-unique-index-where-clause.util.ts 5/5 Entire file deleted - utility for generating WHERE clauses for unique indexes with null equivalence handling
packages/twenty-server/src/engine/core-modules/feature-flag/enums/feature-flag-key.enum.ts 5/5 Removed IS_NULL_EQUIVALENCE_ENABLED from FeatureFlagKey enum
packages/twenty-front/src/generated/graphql.ts 5/5 Removed IS_NULL_EQUIVALENCE_ENABLED from generated GraphQL types
packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/default-feature-flags.ts 5/5 Removed IS_NULL_EQUIVALENCE_ENABLED from default feature flags array
packages/twenty-server/src/engine/workspace-manager/dev-seeder/core/utils/seed-feature-flags.util.ts 5/5 Removed IS_NULL_EQUIVALENCE_ENABLED from feature flag seeding
packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/data-arg.processor.ts 5/5 Removed feature flag parameter from DataArgProcessor and all transformation functions
packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-text-field.util.ts 5/5 Removed isNullEquivalenceEnabled parameter, making null equivalence always active
packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-raw-json-field.util.ts 5/5 Removed feature flag parameter and made null equivalence checking permanent
packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-array-field.util.ts 5/5 Simplified function by removing feature flag parameter
packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-currency-field.util.ts 5/5 Removed isNullEquivalenceEnabled parameter from currency field transformation
packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-full-name-field.util.ts 4/5 Removed feature flag parameter from full name transformation function
packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-actor-field.util.ts 5/5 Removed isNullEquivalenceEnabled parameter from actor field transformation
packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/transform-address-field.util.ts 4/5 Removed feature flag parameter and simplified address field transformation
packages/twenty-server/src/engine/core-modules/record-transformer/utils/transform-emails-value.util.ts 4/5 Standardized null handling by removing feature flag parameter
packages/twenty-server/src/engine/core-modules/record-crud/services/upsert-record.service.ts 4/5 Removed indexPredicate logic and computeUniqueIndexWhereClause import
packages/twenty-server/src/database/commands/upgrade-version-command/1-12/1-12-clean-null-equivalent-values.ts 4/5 Removed feature flag checks from database migration command
packages/twenty-server/src/engine/twenty-orm/entity-manager/workspace-entity-manager.spec.ts 5/5 Removed IS_NULL_EQUIVALENCE_ENABLED from test mock configurations

Confidence score: 4/5

  • This PR represents a clean feature flag removal with well-coordinated changes across the codebase
  • Score reflects one potential concern: the migration command still injects the feature flag repository dependency but no longer uses it, creating minor technical debt
  • Pay close attention to the upsert-record.service.ts file as it removes complex index predicate logic that could affect unique constraint handling

Sequence Diagram

sequenceDiagram
    participant User
    participant "Pull Request System" as PR
    participant "GraphQL Schema" as GQL
    participant "Feature Flag Service" as FFS
    participant "Data Processor" as DP
    participant "Database" as DB

    User->>PR: "Merges PR to remove IS_NULL_EQUIVALENCE_ENABLED"
    PR->>GQL: "Updates FeatureFlagKey enum"
    GQL-->>GQL: "Removes IS_NULL_EQUIVALENCE_ENABLED from enum"
    
    Note over FFS: Feature flag no longer exists in system
    
    User->>DP: "Submits data with null equivalent values"
    DP->>DP: "Processes field transformations"
    DP->>DP: "Applies null equivalence logic unconditionally"
    Note over DP: transformTextField, transformArrayField, etc.<br/>now always convert empty values to null
    
    DP->>DB: "Stores transformed data with null values"
    DB-->>DP: "Confirms data stored"
    DP-->>User: "Returns processed record"
    
    Note over User,DB: Null equivalence behavior is now<br/>permanently enabled for all workspaces
Loading

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Additional Comments (1)

  1. packages/twenty-server/src/database/commands/upgrade-version-command/1-12/1-12-clean-null-equivalent-values.ts, line 56-57 (link)

    style: Feature flag repository is still injected but no longer used in the code

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

22 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

expect(result).toBeNull();
});

it('should return the string when value is empty array', () => {
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.

syntax: Test description says 'return the string' but expects null

Suggested change
it('should return the string when value is empty array', () => {
it('should return null when value is empty array', () => {
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/twenty-server/src/engine/api/common/common-args-processors/data-arg-processor/transformer-utils/__tests__/transform-raw-json-field.util.spec.ts
Line: 16:16

Comment:
**syntax:** Test description says 'return the string' but expects null

```suggestion
  it('should return null when value is empty array', () => {
```

How can I resolve this? If you propose a fix, please make it concise.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Dec 1, 2025

🚀 Preview Environment Ready!

Your preview environment is available at: http://bore.pub:28479

This environment will automatically shut down when the PR is closed or after 5 hours.

@charlesBochet charlesBochet merged commit 68c429a into main Dec 1, 2025
75 checks passed
@charlesBochet charlesBochet deleted the ej/remove-ff branch December 1, 2025 18:06
@twenty-eng-sync
Copy link
Copy Markdown

Hey @etiennejouan! After you've done the QA of your Pull Request, you can mark it as done here. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants