Skip to content

Recipe Tag #5286

Closed
Closed
@lewisward1

Description

@lewisward1

Hello please can you'll me what im doing wrong ? i have spent hours trying to tag a recipe via API but cant get the format - keep getting internal server error. i have cheked the id numbers for the tag and the recipe

this is the code im using , got same in the API too

curl -X 'POST'
'http://192.168.1.242:9926/api/recipes/bulk-actions/tag'
-H 'accept: application/json'
-H 'Authorization: Bearer MY SECRET TOKEN'
-H 'Content-Type: application/json'
-d '{
"recipes": [
"a44da20a-2fa0-44aa-ab4e-7c355e05b70e"
],
"tags": [
{
"name": "Image-Req",
"id": "e1c668af-01db-4f47-ad14-7a663d3722ed",
"slug": "image-req"
}
]
}

Activity

robertdanahome

robertdanahome commented on Apr 13, 2025

@robertdanahome
Contributor

I have hit the same error updating when attempting to add tags to a single recipe (not bulk), and with some AI help I think I found the issue.

Description:

When attempting to update a recipe's tags using the API endpoint PATCH /api/recipes/{recipe_slug}, the request fails with a 500 Internal Server Error. The backend logs show a TypeError: init() missing 1 required positional argument: 'group_id'.

This issue seems to stem from an inconsistency between the Pydantic schema used for API validation and the underlying database model for Tags.

Steps to Reproduce:

  1. Identify an existing recipe slug (YOUR_RECIPE_SLUG), an existing tag name/slug (Existing Tag Name/existing-tag-slug), your Mealie URL (YOUR_MEALIE_URL), your API key (YOUR_MEALIE_API_KEY), and the Group ID the recipe belongs to (YOUR_VALID_GROUP_ID).

  2. Execute the following curl command:

curl -X PATCH 'YOUR_MEALIE_URL/api/recipes/YOUR_RECIPE_SLUG' \
-H 'Authorization: Bearer YOUR_MEALIE_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
--data-raw '{
    "description": "Testing tag update",
    "tags": [
        {
            "name": "Existing Tag Name",
            "slug": "existing-tag-slug",
            "group_id": "YOUR_VALID_GROUP_ID"
        }
    ]
}'

Expected Behavior:

The recipe's tags should be updated successfully with a 200 OK response.

Actual Behavior:

The API returns a 500 Internal Server Error. The Mealie backend logs show the following traceback:

ERROR    YYYY-MM-DDTHH:MM:SS - Unknown Error on recipe controller action
ERROR    YYYY-MM-DDTHH:MM:SS - __init__() missing 1 required positional argument: 'group_id'
Traceback (most recent call last):
  File "/opt/mealie/lib/python3.12/site-packages/mealie/db/models/_model_utils/helpers.py", line 45, in safe_call
    return func(**get_valid_call(func, dict_args))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: __init__() missing 1 required positional argument: 'group_id'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/opt/mealie/lib/python3.12/site-packages/mealie/routes/recipe/recipe_crud_routes.py", line 413, in patch_one
    recipe = self.service.patch_one(slug, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mealie/lib/python3.12/site-packages/mealie/services/recipe/recipe_service.py", line 411, in patch_one
    new_data = self.group_recipes.patch(recipe.slug, patch_data.model_dump(exclude_unset=True))
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mealie/lib/python3.12/site-packages/mealie/repos/repository_generic.py", line 247, in patch
    return self.update(match_value, entry_as_dict)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mealie/lib/python3.12/site-packages/mealie/repos/repository_generic.py", line 216, in update
    entry.update(session=self.session, **new_data)
  File "/opt/mealie/lib/python3.12/site-packages/mealie/db/models/_model_base.py", line 32, in update
    self.__init__(*args, **kwargs)
  File "<string>", line 6, in __init__
  File "/opt/mealie/lib/python3.12/site-packages/mealie/db/models/recipe/api_extras.py", line 19, in wrapper
    return func(*args, extras=extras, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mealie/lib/python3.12/site-packages/mealie/db/models/_model_utils/auto_init.py", line 187, in wrapper
    instances = handle_many_to_many(session, get_attr, relation_cls, val)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mealie/lib/python3.12/site-packages/mealie/db/models/_model_utils/auto_init.py", line 73, in handle_many_to_many
    return handle_one_to_many_list(session, get_attr, relation_cls, all_elements)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mealie/lib/python3.12/site-packages/mealie/db/models/_model_utils/auto_init.py", line 100, in handle_one_to_many_list
    new_elems = [safe_call(relation_cls, elem.copy(), session=session) for elem in elems_to_create]
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/mealie/lib/python3.12/site-packages/mealie/db/models/_model_utils/helpers.py", line 47, in safe_call
    return func(**dict_args)
           ^^^^^^^^^^^^^^^^^
TypeError: __init__() missing 1 required positional argument: 'group_id'

Root Cause Analysis:

  • The Tag database model (mealie/db/models/recipe/tag.py) requires group_id in its init method:
class Tag(SqlAlchemyBase, BaseMixins):
    # ...
    group_id: Mapped[guid.GUID] = mapped_column(guid.GUID, sa.ForeignKey("groups.id"), nullable=False, index=True)
    # ...
    def __init__(self, name, group_id, **_) -> None: # Requires group_id
        self.group_id = group_id
        self.name = name.strip()
        self.slug = slugify(self.name)
  • However, the Pydantic schema RecipeTag (mealie/schema/recipe/recipe.py), used to validate the tags array in the PATCH request payload, does not define group_id:
class RecipeTag(MealieModel):
    id: UUID4 | None = None
    name: str
    slug: str # Missing group_id
    # ...
  • Similarly, the TagBase schema (mealie/schema/recipe/recipe_category.py), used by the bulk tag action endpoint (/api/recipes/bulk-actions/tag), also lacks group_id.

  • Because group_id is not defined in the API validation schemas, Pydantic strips this field from the incoming request data before it reaches the database layer.

  • When the backend attempts to initialize the Tag database model using this processed data, the required group_id argument is missing, causing the TypeError.

Suggested Fix:

Modify the relevant Pydantic schemas to include the group_id field, making it optional to avoid breaking other potential uses:

In mealie/schema/recipe/recipe.py:

class RecipeTag(MealieModel):
    id: UUID4 | None = None
    group_id: UUID4 | None = None # Add this line
    name: str
    slug: str
    # ...

In mealie/schema/recipe/recipe_category.py (affecting TagBase via inheritance):

class CategoryBase(CategoryIn):
    id: UUID4
    group_id: UUID4 | None = None # Add this line
    slug: str
    # ...

This change allows the group_id to pass through API validation and be available when the Tag database model is initialized.

Submitted as pull request #5342

robertdanahome

robertdanahome commented on Apr 18, 2025

@robertdanahome
Contributor

OP, the maintainers just merged the fix I made. This should be in the next release, or if you could patch in the pull request I made. I haven't tried it with batch updates (which this should have fixed), but am able to update tags on individual recipes.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @lewisward1@robertdanahome

      Issue actions

        Recipe Tag · Issue #5286 · mealie-recipes/mealie