Skip to content

Raise an error for nested Strawberry field metadata - #4595

Merged
patrick91 merged 9 commits into
mainfrom
fix/nested-field-annotation-error
Aug 29, 2026
Merged

Raise an error for nested Strawberry field metadata#4595
patrick91 merged 9 commits into
mainfrom
fix/nested-field-annotation-error

Conversation

@patrick91

@patrick91 patrick91 commented Aug 29, 2026

Copy link
Copy Markdown
Member

Summary

  • reject strawberry.field() metadata nested below the owning class-field annotation
  • preserve valid root field metadata and nested lazy, union, and enum metadata
  • add a source-aware Strawberry exception, documentation, tests, and release-note examples

Testing

  • uv run pytest tests/types -q
  • uv run pytest tests/types/test_annotated_fields_future_annotations.py tests/types/test_object_types.py -q
  • uv run pytest tests/fields/test_arguments.py tests/fields/test_resolvers.py -q
  • uv run pytest tests/schema/test_schema_generation.py tests/schema/test_directives.py -q
  • uv run mypy --config-file mypy.ini strawberry/types/object_type.py strawberry/exceptions/invalid_strawberry_field_annotation.py
  • uv run pre-commit run --files RELEASE.md docs/types/object-types.md docs/errors/invalid-strawberry-field-annotation.md strawberry/exceptions/__init__.py strawberry/exceptions/invalid_strawberry_field_annotation.py strawberry/types/object_type.py tests/types/test_object_types.py tests/types/test_annotated_fields_future_annotations.py

Summary by Sourcery

Reject nested strawberry.field() metadata with actionable diagnostics while preserving valid annotation metadata.

Bug Fixes:

  • Raise a clear, source-aware error when strawberry.field() metadata is nested inside a class-field annotation instead of silently ignoring it.

Enhancements:

  • Preserve valid root field metadata and nested lazy, union, and enum metadata while caching annotation evaluation and validation.

Documentation:

  • Document the invalid nested field metadata error and show how to place strawberry.field() on the outermost annotation.

Tests:

  • Add coverage for nested field metadata, forward references, unresolved types, metadata preservation, and validation caching.

@github-actions

Copy link
Copy Markdown
Contributor

Thanks for adding the RELEASE.md file!

Below is the changelog that will be used for the release.


This release fixes silently ignored strawberry.field() metadata in nested type
annotations.

Strawberry now raises a clear error when field metadata is placed below the
class-field annotation, such as on a list item, and explains that it must be moved
to the outermost Annotated metadata for the field.

For example, Strawberry now reports this misplaced metadata:

from typing import Annotated

import strawberry


@strawberry.type
class Query:
    names: list[Annotated[str, strawberry.field(description="A name")]]

Move strawberry.field() to the field's outermost Annotated metadata:

@strawberry.type
class Query:
    names: Annotated[list[str], strawberry.field(description="The names")]

This release was contributed by @patrick91 in #4595

@sourcery-ai sourcery-ai Bot left a comment

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.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="strawberry/types/object_type.py" line_range="97-101" />
<code_context>
         ):
             raise MultipleStrawberryFieldsError(field_name=field_name, cls=cls)

+        if _contains_strawberry_field(first):
+            raise InvalidStrawberryFieldAnnotationError(
+                field_name=field_name,
+                cls=cls,
+            )
+
         if not strawberry_fields:
</code_context>
<issue_to_address>
**issue (bug_risk):** Nested `strawberry.field()` metadata is not rejected when the wrapped type contains an unresolved forward reference: `evaluate_forward_ref()` raises `NameError`, the existing `except` block continues, and execution never reaches `_contains_strawberry_field(first)`. The misplaced metadata is therefore still silently ignored.

**Triggers:** When a nested field annotation refers to a type that is unavailable while the owning Strawberry class is being processed, such as a type imported only under `TYPE_CHECKING` or declared later.

**Suggested fix:** Inspect the resolved portions of the annotation before skipping unresolved forward references, or preserve the annotation for a later validation pass so nested `StrawberryField` metadata is still detected.
</issue_to_address>

Sourcery assessment

Approval pending. 1 finding to address first.

Blocking findings: strawberry/types/object_type.py:101


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread strawberry/types/object_type.py Outdated
@greptile-apps

greptile-apps Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Strawberry now detects and reports strawberry.field() metadata nested below the owning class-field annotation.

  • Adds recursive nested-field metadata validation during Strawberry type construction.
  • Introduces a source-aware InvalidStrawberryFieldAnnotationError and exports it publicly.
  • Documents correct outermost Annotated placement and adds coverage for nested wrappers, deferred annotations, lazy references, unions, and enums.

Confidence Score: 5/5

The PR appears safe to merge with no actionable correctness, security, or compatibility issues identified.

The recursive check is limited to StrawberryField instances below the owning annotation, while valid root field metadata and supported nested lazy, union, and enum metadata remain preserved.

Important Files Changed

Filename Overview
strawberry/types/object_type.py Adds recursive detection of misplaced nested StrawberryField metadata while retaining valid top-level metadata processing.
strawberry/exceptions/invalid_strawberry_field_annotation.py Defines a focused, source-aware exception with actionable guidance for correcting nested field metadata.
tests/types/test_object_types.py Covers rejection through list and optional wrappers and verifies preservation of nested union and enum metadata.
tests/types/test_annotated_fields_future_annotations.py Covers future-annotation rejection and verifies nested lazy metadata remains supported.
docs/errors/invalid-strawberry-field-annotation.md Documents the new error condition and the correct metadata placement.

Reviews (1): Last reviewed commit: "Raise error for nested Strawberry field ..." | Re-trigger Greptile

@patrick91

Copy link
Copy Markdown
Member Author

@sourcery-ai review

sourcery-ai[bot]
sourcery-ai Bot previously approved these changes Aug 29, 2026

@sourcery-ai sourcery-ai Bot left a comment

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.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codspeed-hq

codspeed-hq Bot commented Aug 29, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 34 untouched benchmarks


Comparing fix/nested-field-annotation-error (3443e30) with main (9f9e840)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (62edaec) during the generation of this report, so 9f9e840 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@sourcery-ai

sourcery-ai Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Warning

Sourcery was unable to dismiss its earlier approval of this pull request, because the latest commits introduced blocking findings. The approval above no longer reflects the current commits.

How to resolve this

Add the Sourcery app under Restrict who can dismiss pull request reviews in this repository's branch protection rules. Sourcery only ever dismisses its own reviews. It does not dismiss reviews from anyone else.

@patrick91

Copy link
Copy Markdown
Member Author

@sourcery-ai review

@sourcery-ai sourcery-ai Bot left a comment

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.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="strawberry/types/object_type.py" line_range="73-79" />
<code_context>
         else:
             annotation = raw_annotation

-        if get_origin(annotation) is not Annotated:
-            continue
+        if get_origin(annotation) is Annotated:
</code_context>
<issue_to_address>
**issue (bug_risk):** When a class annotation is a string forward reference that cannot be evaluated, `_process_annotated_fields` continues before reaching `_contains_strawberry_field`, so nested `strawberry.field()` metadata is not rejected by the new exception and the field instead proceeds to the later unresolved-field failure or is silently omitted from annotated-field processing.

**Triggers:** When nested field metadata contains a type that is unresolved during class decoration, especially with `TYPE_CHECKING` imports or a type declared later.

**Suggested fix:** Inspect the raw forward-reference structure for nested `StrawberryField` metadata, or defer and retain validation state so the nested metadata is checked after forward references become resolvable.
</issue_to_address>

Sourcery assessment

Approval pending. 1 finding to address first.

Blocking findings: strawberry/types/object_type.py:79


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread strawberry/types/object_type.py
@sourcery-ai
sourcery-ai Bot dismissed their stale review August 29, 2026 10:35

Sourcery withdrew this approval because the latest commits introduced blocking findings.

@patrick91
patrick91 merged commit 4fd44aa into main Aug 29, 2026
83 checks passed
@patrick91
patrick91 deleted the fix/nested-field-annotation-error branch August 29, 2026 11:03
@botberry

Copy link
Copy Markdown
Member

This PR was published as 0.324.3. Thank you for contributing!

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