Skip to content

Adding Recipe via API leads to 500 Internal Server Error. #4356

@neXyon

Description

@neXyon

Tandoor Version

2.3.6

Setup

Others (please state below)

Reverse Proxy

Others (please state below)

Other

Arch Linux AUR package tandoor-recipes with nginx

Bug description

I just set up Tandoor for the first time and I'm now trying to write a script to import my existing recipes, but I get either a success or one of the following two errors. Here is an example to trigger the issue:

import requests

# set these correctly!
base_url = 'https://app.tandoor.dev'
token = 'abcdef123567890abc123'

headers = {'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'}

json_request=b'{"name": "Test", "description": "Test", "keywords": [], "working_time": 1, "waiting_time": 0, "internal": true, "nutrition": {"source": "", "calories": 100, "fats": 10, "carbohydrates": 10, "proteins": 10}, "steps": [{"type": "TEXT", "ingredients": [{"food": {"name": "Test"}, "unit": {"name": "g"}, "amount": 1, "note": ""}, {"food": {"name": "Test2"}, "unit": {"name": "g"}, "amount": 1, "note": ""}, {"food": {"name": "Test3"}, "unit": {"name": "g"}, "amount": 1, "note": ""}, {"food": {"name": "Test4"}, "unit": {"name": "g"}, "amount": 1, "note": ""}, {"food": {"name": "Test5"}, "unit": {"name": "g"}, "amount": 1, "note": ""}, {"food": {"name": "Test6"}, "unit": {"name": "g"}, "amount": 1, "note": ""}, {"food": {"name": "Test7"}, "unit": {"name": "g"}, "amount": 1, "note": ""}], "instruction": "Test"}], "servings": 1, "servings_text": "", "source_url": ""}'

answer = requests.post(f'{base_url}/api/recipe/', headers=headers, data=json_request)

As you can see, there are a few ingredients an when I change their count I can change the outcome, even though these should work trivially. With this I get the following first error, if I remove one ingredient at the end it works, if I remove another one, I get the second error:

Traceback (most recent call last):
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/fields/related_descriptors.py", line 243, in __get__
    rel_obj = self.field.get_cached_value(instance)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/fields/mixins.py", line 37, in get_cached_value
    return instance._state.fields_cache[self.cache_name]
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
KeyError: 'space'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/gunicorn/workers/sync.py", line 134, in handle
    self.handle_request(listener, req, client, addr)
    ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/gunicorn/workers/sync.py", line 177, in handle_request
    respiter = self.wsgi(environ, resp.start_response)
  File "/usr/share/tandoor/recipes/wsgi.py", line 34, in application
    return _application(environ, start_response)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/wsgi.py", line 124, in __call__
    response = self.get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/base.py", line 140, in get_response
    response = self._middleware_chain(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/corsheaders/middleware.py", line 56, in __call__
    result = self.get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/whitenoise/middleware.py", line 123, in __call__
    return self.get_response(request)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/allauth/usersessions/middleware.py", line 18, in __call__
    response = self.get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/cookbook/helper/scope_middleware.py", line 80, in __call__
    return self.get_response(request)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/allauth/account/middleware.py", line 36, in middleware
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
    return view_func(request, *args, **kwargs)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/views.py", line 512, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/mixins.py", line 20, in create
    headers = self.get_success_headers(serializer.data)
                                       ^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/serializers.py", line 573, in data
    ret = super().data
          ^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/serializers.py", line 251, in data
    self._data = self.to_representation(self.instance)
                 ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/serializers.py", line 540, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
                            ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/fields.py", line 1870, in to_representation
    return method(value)
  File "/usr/share/tandoor/cookbook/serializer.py", line 1158, in get_food_properties
    return fph.calculate_recipe_properties(obj)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
  File "/usr/share/tandoor/cookbook/helper/property_helper.py", line 45, in calculate_recipe_properties
    conversions = uch.get_conversions(i)
  File "/usr/share/tandoor/cookbook/helper/unit_conversion_helper.py", line 119, in get_conversions
    if c.space == self.space:
       ^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/fields/related_descriptors.py", line 261, in __get__
    rel_obj = self.get_object(instance)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/fields/related_descriptors.py", line 224, in get_object
    return qs.get(self.field.get_reverse_related_filter(instance))
           ~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/query.py", line 623, in get
    clone = clone.order_by()
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/query.py", line 1727, in order_by
    obj.query.add_ordering(*field_names)
    ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/sql/query.py", line 2284, in add_ordering
    def add_ordering(self, *ordering):
    
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/gunicorn/workers/base.py", line 204, in handle_abort
    sys.exit(1)
    ~~~~~~~~^^^
SystemExit: 1

The important line here seems to be if c.space == self.space: in cookbook/helper/unit_conversion_helper.py:119, while for the second error, the important line seems to be if (uc.food is None or uc.food == food) and uc.converted_amount > 0 and uc.base_amount > 0: in cookbook/helper/unit_conversion_helper.py:138:

Traceback (most recent call last):
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/fields/related_descriptors.py", line 243, in __get__
    rel_obj = self.field.get_cached_value(instance)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/fields/mixins.py", line 37, in get_cached_value
    return instance._state.fields_cache[self.cache_name]
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
KeyError: 'food'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/gunicorn/workers/sync.py", line 134, in handle
    self.handle_request(listener, req, client, addr)
    ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/gunicorn/workers/sync.py", line 177, in handle_request
    respiter = self.wsgi(environ, resp.start_response)
  File "/usr/share/tandoor/recipes/wsgi.py", line 34, in application
    return _application(environ, start_response)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/wsgi.py", line 124, in __call__
    response = self.get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/base.py", line 140, in get_response
    response = self._middleware_chain(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/corsheaders/middleware.py", line 56, in __call__
    result = self.get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/whitenoise/middleware.py", line 123, in __call__
    return self.get_response(request)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/allauth/usersessions/middleware.py", line 18, in __call__
    response = self.get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/utils/deprecation.py", line 120, in __call__
    response = response or self.get_response(request)
                           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/cookbook/helper/scope_middleware.py", line 80, in __call__
    return self.get_response(request)
           ~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/allauth/account/middleware.py", line 36, in middleware
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
    return view_func(request, *args, **kwargs)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
           ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/views.py", line 512, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/mixins.py", line 20, in create
    headers = self.get_success_headers(serializer.data)
                                       ^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/serializers.py", line 573, in data
    ret = super().data
          ^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/serializers.py", line 251, in data
    self._data = self.to_representation(self.instance)
                 ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/serializers.py", line 540, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
                            ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/rest_framework/fields.py", line 1870, in to_representation
    return method(value)
  File "/usr/share/tandoor/cookbook/serializer.py", line 1158, in get_food_properties
    return fph.calculate_recipe_properties(obj)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
  File "/usr/share/tandoor/cookbook/helper/property_helper.py", line 45, in calculate_recipe_properties
    conversions = uch.get_conversions(i)
  File "/usr/share/tandoor/cookbook/helper/unit_conversion_helper.py", line 120, in get_conversions
    r = self._uc_convert(c, ingredient.amount, ingredient.unit, ingredient.food)
  File "/usr/share/tandoor/cookbook/helper/unit_conversion_helper.py", line 138, in _uc_convert
    if (uc.food is None or uc.food == food) and uc.converted_amount > 0 and uc.base_amount > 0:
        ^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/fields/related_descriptors.py", line 261, in __get__
    rel_obj = self.get_object(instance)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/fields/related_descriptors.py", line 224, in get_object
    return qs.get(self.field.get_reverse_related_filter(instance))
           ~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/query.py", line 631, in get
    num = len(clone)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/query.py", line 368, in __len__
    self._fetch_all()
    ~~~~~~~~~~~~~~~^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/query.py", line 1954, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
                         ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/query.py", line 93, in __iter__
    results = compiler.execute_sql(
        chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size
    )
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/models/sql/compiler.py", line 1623, in execute_sql
    cursor.execute(sql, params)
    ~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/backends/utils.py", line 79, in execute
    return self._execute_with_wrappers(
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        sql, params, many=False, executor=self._execute
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    )
    ^
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/django/db/backends/utils.py", line 105, in _execute
    return self.cursor.execute(sql, params)
           ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/lib/python3.13/encodings/utf_8.py", line 15, in decode
    def decode(input, errors='strict'):
    
  File "/usr/share/tandoor/venv/lib/python3.13/site-packages/gunicorn/workers/base.py", line 204, in handle_abort
    sys.exit(1)
    ~~~~~~~~^^^
SystemExit: 1

Relevant logs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions