---
title: 0.279.0 Breaking Changes
slug: breaking-changes/0.279.0
---

# v0.279.0 Breaking Changes

This release changes the `strawberry.Maybe` type definition to provide a more
consistent and intuitive API for handling optional fields.

## What Changed

The `Maybe` type definition has been changed from:

```python
Maybe: TypeAlias = Union[Some[Union[T, None]], None]
```

to:

```python
Maybe: TypeAlias = Union[Some[T], None]
```

## Impact on Your Code

### Type Annotations

If you were using `Maybe[T]` and expecting to handle explicit `null` values, you
now need to explicitly declare this with `Maybe[T | None]`:

```python
# Before (0.278.0 and earlier)
field: strawberry.Maybe[str]  # Could handle Some(None)

# After (0.279.0+)
field: strawberry.Maybe[str]  # Only handles Some("value") or None (absent)
field: strawberry.Maybe[str | None]  # Handles Some("value"), Some(None), or None
```

### Runtime Behavior

The runtime behavior changes to provide more consistent field checking:

- `Maybe[str]` now represents "field present with non-null value" or "field
  absent"
- `Maybe[str | None]` represents "field present with value", "field present but
  null", or "field absent"

This means `Maybe[str]` can no longer receive explicit `null` values - they will
cause a validation error.

### Consistent Field Checking

This change provides a single, consistent way to check if a field was provided,
regardless of whether the field allows null values:

```python
@strawberry.input
class UpdateUserInput:
    # Can be provided with a value or not provided at all
    name: strawberry.Maybe[str]

    # Can be provided with a value, provided as null, or not provided at all
    phone: strawberry.Maybe[str | None]


@strawberry.mutation
def update_user(input: UpdateUserInput) -> User:
    # Same checking pattern for both fields
    if input.name is not None:  # Field was provided
        user.name = input.name.value  # Type checker knows this is str

    if input.phone is not None:  # Field was provided
        user.phone = input.phone.value  # Type checker knows this is str | None
```

The key benefit is that `if field is not None` now consistently means "field was
provided" for all Maybe fields.

## Migration

### Automatic Migration

Strawberry provides a codemod to automatically update your code:

```bash
strawberry upgrade maybe-optional
```

The codemod will automatically convert `Maybe[T]` to `Maybe[T | None]` to
maintain the previous behavior.

### Manual Migration

Review your `Maybe` usage and decide whether you need the union type:

```python
# If you only need "present" vs "absent" (most common case)
field: strawberry.Maybe[str]

# If you need "present with value", "present but null", and "absent"
field: strawberry.Maybe[str | None]
```

## Why This Change?

After extensive discussion, we decided that changing `Maybe` to `Some[T] | None`
(instead of `Some[T | None] | None`) provides the best developer experience
because:

1. **Consistent field checking**: You can always use `if field is not None:` to
   check if a field was provided, regardless of whether the field allows null
   values

2. **Preserves existing behavior**: You can still get the previous behavior by
   using `Maybe[T | None]` when you need to handle explicit nulls

3. **Better type safety**: `Maybe[str]` now properly indicates that the field
   cannot be null, while `Maybe[str | None]` explicitly allows nulls

4. **Cleaner API**: There's now "one true way" to check if a field was provided,
   making the API more intuitive

The new approach provides both simplicity for common cases and flexibility for
complex scenarios where null handling is needed.

## Need Help?

- See the [Maybe documentation](../types/maybe.md) for comprehensive usage
  examples
- Check the
  [migration guide](../types/maybe.md#migration-from-previous-versions) for
  detailed migration instructions
- If you encounter issues, please
  [report them on GitHub](https://github.com/strawberry-graphql/strawberry/issues)
