Skip to content

fix: prevent duplicate field names through configure - #787

Merged
stuebingerb merged 1 commit into
mainfrom
fix/prevent-duplicate-field-names
Nov 13, 2026
Merged

stuebingerb merged 1 commit into
mainfrom
fix/prevent-duplicate-field-names

Conversation

@stuebingerb

Copy link
Copy Markdown
Owner

Resolves #781

@coderabbitai

coderabbitai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Explain Change →

No actionable comments were generated in the recent review.

Summary

Summary by CodeRabbit

  • Bug Fixes
    • Schema generation now consistently validates field names and rejects duplicate names across object and input fields, including configured names.
    • Introspected input types now include their fields in the schema.
    • Reserved-name errors for input types now identify the correct type.

Schema compilation now validates field names and rejects duplicates as fields are added to object and input types. Input fields are no longer omitted based on the NotIntrospected annotation. Tests cover duplicate and swapped configured property names.

Changes: Schema field validation

Layer / File(s) Summary
Shared validation and object fields
kgraphql/src/main/kotlin/de/stuebingerb/kgraphql/schema/structure/SchemaCompilation.kt, kgraphql/src/test/kotlin/de/stuebingerb/kgraphql/integration/ObjectTest.kt
Object Kotlin, extension, union, and dataloaded fields are added through shared name validation. Tests check that duplicate configured names raise a SchemaException and swapped names are accepted.
Input field validation
kgraphql/src/main/kotlin/de/stuebingerb/kgraphql/schema/structure/SchemaCompilation.kt, kgraphql/src/test/kotlin/de/stuebingerb/kgraphql/integration/InputObjectTest.kt, kgraphql/src/test/kotlin/de/stuebingerb/kgraphql/specification/typesystem/InputObjectsSpecificationTest.kt
Sealed one-of alternatives and constructor parameters use shared name validation. Tests cover duplicate configured names, swapped names, and updated error expectations.

Change: Bug fix

Merge Risk: Minimal · up to 172b2

The change rejects duplicate field names that configure can produce, and swapping two names is still allowed. No actionable merge-blocking risk was identified in the supplied changes.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title names the change, which is preventing duplicate field names when configure renames a property. The changeset adds field-name validation through shared addField and addInputValue helper…
Description check Passed The description only references issue #781 with 'Resolves #781'. It is brief, but it relates to the changeset because the linked issue concerns duplicate input-field names created by configure, whic…
Linked Issues check Passed Issue #781 requires that PropertyDSL must not create duplicate input-field names when configure renames a property (example: InputObject::bar renamed to foo while InputObject::foo exists). The PR summ…
Out of Scope Changes check Passed The changes center on duplicate-name validation in SchemaCompilation.kt (addField for object fields, addInputValue for input fields) and on tests for the duplicate-name scenario in InputObjectTest.kt,…
Full details: Title check

Explanation

The title names the change, which is preventing duplicate field names when configure renames a property. The changeset adds field-name validation through shared addField and addInputValue helpers that reject duplicates, and adds tests for the duplicate-name case. The title follows the conventional commits prefix fix:. It is 54 characters, slightly over the 50-character guideline.

Full details: Description check

Explanation

The description only references issue #781 with 'Resolves #781'. It is brief, but it relates to the changeset because the linked issue concerns duplicate input-field names created by configure, which the changes address.

Full details: Linked Issues check

Explanation

Issue #781 requires that PropertyDSL must not create duplicate input-field names when configure renames a property (example: InputObject::bar renamed to foo while InputObject::foo exists). The PR summary for SchemaCompilation.kt states that input fields are accumulated through addInputValue, which validates names and rejects duplicates across sealed one-of fields and constructor parameters. The old per-type duplicate tracking was removed in favor of this shared check. InputObjectTest.kt adds a test where two input properties configured to the same name raise SchemaException. The same file adds a test showing that swapping two names is accepted and yields both fields. The visible portion of SchemaCompilation.kt confirms that object fields use the shared addField validation. The addInputValue body was not readable because the file read was truncated at 16000 bytes. The PASS relies on the PR summary and the described tests for the input path. The repository diff could not be read because changed blobs are missing from the checkout.

Full details: Out of Scope Changes check

Explanation

The changes center on duplicate-name validation in SchemaCompilation.kt (addField for object fields, addInputValue for input fields) and on tests for the duplicate-name scenario in InputObjectTest.kt, ObjectTest.kt, and InputObjectsSpecificationTest.kt. The removal of the NotIntrospected check lets introspected input types use the same validation path. This is a broader behavior change, but it follows from unifying validation and is not shown to be unrelated. The changed expected error text (PersonInput name, 'Cannot add field with duplicated name') follows from the shared validation path. No unrelated feature change appears in the summary. The full diff was not readable, so the NotIntrospected removal was assessed from the summary only.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f89675d5-0354-40ae-b860-6be715f16fca
Commits

Reviewing files that changed from the base of the PR and between f11820e and 172b272.

Files selected for processing: 4

  • kgraphql/src/main/kotlin/de/stuebingerb/kgraphql/schema/structure/SchemaCompilation.kt
  • kgraphql/src/test/kotlin/de/stuebingerb/kgraphql/integration/InputObjectTest.kt
  • kgraphql/src/test/kotlin/de/stuebingerb/kgraphql/integration/ObjectTest.kt
  • kgraphql/src/test/kotlin/de/stuebingerb/kgraphql/specification/typesystem/InputObjectsSpecificationTest.kt

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@codecov

codecov Bot commented Nov 13, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.07843% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.49%. Comparing base (f11820e) to head (172b272).

Files with missing lines Patch % Lines
...erb/kgraphql/schema/structure/SchemaCompilation.kt 96.07% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #787      +/-   ##
==========================================
+ Coverage   84.46%   84.49%   +0.02%     
==========================================
  Files         151      151              
  Lines        5112     5113       +1     
  Branches      893      891       -2     
==========================================
+ Hits         4318     4320       +2     
+ Misses        492      491       -1     
  Partials      302      302              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="kgraphql/src/main/kotlin/de/stuebingerb/kgraphql/schema/structure/SchemaCompilation.kt">

<violation number="1" location="kgraphql/src/main/kotlin/de/stuebingerb/kgraphql/schema/structure/SchemaCompilation.kt:454">
P2: The `@NotIntrospected` check in `handleInputType` was removed without explanation. Input classes with that annotation used to fail with "must define one or more fields", and now they compile into normal input types. This change is unrelated to duplicate-name detection, so either restore the check or document the intended behavior in the PR.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant Config as Schema Configuration DSL
    participant Compiler as SchemaCompilation
    participant DuplicateGuard as Duplicate Field Guard
    participant Validator as Name Validator
    
    Note over Config,Validator: Schema Validation Flow
    
    Config->>Compiler: configure(inputType/type definitions)
    
    alt Object type compilation
        Compiler->>Compiler: Collect memberProperties
        Compiler->>DuplicateGuard: addField(field)
        DuplicateGuard->>Validator: validateName(field.name)
        Validator-->>DuplicateGuard: Name valid
        alt Field name already exists
            DuplicateGuard->>Compiler: Throw SchemaException (duplicate)
        else Unique field name
            DuplicateGuard->>Compiler: Return field list
        end
    else Input type compilation
        Compiler->>Compiler: Collect constructor parameters
        Compiler->>DuplicateGuard: addInputValue(value)
        DuplicateGuard->>Validator: validateName(value.name)
        Validator-->>DuplicateGuard: Name valid
        alt Field name already exists
            DuplicateGuard->>Compiler: Throw SchemaException (duplicate)
        else Unique field name
            DuplicateGuard->>Compiler: Return input field list
        end
    else OneOf sealed input compilation
        Compiler->>Compiler: Collect sealed subclasses
        Compiler->>DuplicateGuard: addInputValue(value)
        DuplicateGuard->>Validator: validateName(value.name)
        Validator-->>DuplicateGuard: Name valid
        alt Field name already exists
            DuplicateGuard->>Compiler: Throw SchemaException (duplicate)
        else Unique field name
            DuplicateGuard->>Compiler: Return input field list
        end
    end
    
    Compiler->>Compiler: Build Type.Object/Type.InputObject
    Compiler->>Config: Return compiled schema
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

),
type
)
val fields = mutableListOf<InputValue<*>>()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The @NotIntrospected check in handleInputType was removed without explanation. Input classes with that annotation used to fail with "must define one or more fields", and now they compile into normal input types. This change is unrelated to duplicate-name detection, so either restore the check or document the intended behavior in the PR.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At kgraphql/src/main/kotlin/de/stuebingerb/kgraphql/schema/structure/SchemaCompilation.kt, line 454:

<comment>The `@NotIntrospected` check in `handleInputType` was removed without explanation. Input classes with that annotation used to fail with "must define one or more fields", and now they compile into normal input types. This change is unrelated to duplicate-name detection, so either restore the check or document the intended behavior in the PR.</comment>

<file context>
@@ -445,66 +451,60 @@ open class SchemaCompilation(
-                        ),
-                        type
-                    )
+        val fields = mutableListOf<InputValue<*>>()
+        if (kClass.isSealed) {
+            // OneOf input types have one field per allowed sub type
</file context>

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The previous failure was also wrong/unhelpful, and classes annotated with @NotIntrospected were not handled anywhere else during schema compilation. This is a topic for another day.

@github-actions

Copy link
Copy Markdown

🐰 Bencher Report

ProjectKGraphQL
Branchfix/prevent-duplicate-field-names
Testbedubuntu-latest
Click to view all benchmark results
BenchmarkThroughputBenchmark Result
operations / second (ops/s)
(Result Δ%)
Lower Boundary
operations / second (ops/s)
(Limit %)
de.stuebingerb.kgraphql.FunctionExecutionBenchmark.benchmarkFunctionExecution📈 view plot
🚷 view threshold
5,753,647.77 ops/s
(-5.47%)Baseline: 6,086,850.96 ops/s
3,786,980.07 ops/s
(65.82%)
de.stuebingerb.kgraphql.ParallelExecutionBenchmark.queryBenchmark📈 view plot
🚷 view threshold
1.30 ops/s
(+0.13%)Baseline: 1.30 ops/s
1.29 ops/s
(99.50%)
de.stuebingerb.kgraphql.QueryBenchmark.executionError📈 view plot
🚷 view threshold
17,997.71 ops/s
(-15.18%)Baseline: 21,219.01 ops/s
5,724.86 ops/s
(31.81%)
de.stuebingerb.kgraphql.QueryBenchmark.inputFromDocument📈 view plot
🚷 view threshold
24,998.35 ops/s
(-4.81%)Baseline: 26,261.77 ops/s
10,466.56 ops/s
(41.87%)
de.stuebingerb.kgraphql.QueryBenchmark.inputFromVariable📈 view plot
🚷 view threshold
24,322.04 ops/s
(-4.87%)Baseline: 25,566.98 ops/s
9,881.70 ops/s
(40.63%)
de.stuebingerb.kgraphql.QueryBenchmark.largeList📈 view plot
🚷 view threshold
4.51 ops/s
(-6.37%)Baseline: 4.81 ops/s
3.25 ops/s
(72.18%)
de.stuebingerb.kgraphql.QueryBenchmark.largeListWithFragment📈 view plot
🚷 view threshold
5.05 ops/s
(-6.33%)Baseline: 5.39 ops/s
3.72 ops/s
(73.55%)
de.stuebingerb.kgraphql.QueryBenchmark.manyChildren📈 view plot
🚷 view threshold
166.97 ops/s
(-13.24%)Baseline: 192.46 ops/s
91.84 ops/s
(55.00%)
de.stuebingerb.kgraphql.QueryBenchmark.manyChildrenWithFragment📈 view plot
🚷 view threshold
187.87 ops/s
(-8.90%)Baseline: 206.22 ops/s
89.20 ops/s
(47.48%)
de.stuebingerb.kgraphql.QueryBenchmark.manyDataChildren📈 view plot
🚷 view threshold
8.85 ops/s
(-0.97%)Baseline: 8.94 ops/s
8.62 ops/s
(97.31%)
de.stuebingerb.kgraphql.QueryBenchmark.manyOperations📈 view plot
🚷 view threshold
297.45 ops/s
(-8.27%)Baseline: 324.25 ops/s
142.51 ops/s
(47.91%)
de.stuebingerb.kgraphql.QueryBenchmark.manyOperationsWithFragment📈 view plot
🚷 view threshold
301.12 ops/s
(-8.88%)Baseline: 330.48 ops/s
146.45 ops/s
(48.64%)
de.stuebingerb.kgraphql.QueryBenchmark.nestedObject📈 view plot
🚷 view threshold
8,072.65 ops/s
(-10.07%)Baseline: 8,976.76 ops/s
3,654.24 ops/s
(45.27%)
de.stuebingerb.kgraphql.RequestCachingBenchmark.invalidRequest📈 view plot
🚷 view threshold
156,780.90 ops/s
(-2.22%)Baseline: 160,337.37 ops/s
80,483.21 ops/s
(51.33%)
de.stuebingerb.kgraphql.RequestCachingBenchmark.largeRequest📈 view plot
🚷 view threshold
8,007.82 ops/s
(-15.05%)Baseline: 9,426.76 ops/s
3,793.82 ops/s
(47.38%)
de.stuebingerb.kgraphql.RequestCachingBenchmark.smallRequest📈 view plot
🚷 view threshold
12,310.21 ops/s
(-10.74%)Baseline: 13,791.01 ops/s
4,905.24 ops/s
(39.85%)
de.stuebingerb.kgraphql.SimpleExecutionOverheadBenchmark.benchmark📈 view plot
🚷 view threshold
452,804.84 ops/s
(-16.24%)Baseline: 540,623.31 ops/s
220,539.75 ops/s
(48.71%)
🐰 View full continuous benchmarking report in Bencher

@stuebingerb
stuebingerb merged commit 59ad2b2 into main Nov 13, 2026
14 checks passed
@stuebingerb
stuebingerb deleted the fix/prevent-duplicate-field-names branch November 13, 2026 13:33
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.

PropertyDSL allows to create fields with duplicate names

1 participant