We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Catch and handle EmptyResultSet error when trying to cache metadata labels
EmptyResultSet

Sentry Issue: [KOLIBRI-BACKEND-2E9](https://learningequality.sentry.io/issues/4005137733/?referrer=github_integration)

```
EmptyResultSet: 
(16 additional frame(s) were not displayed)
...
  File "django/db/models/sql/query.py", line 233, in __str__
    sql, params = self.sql_with_params()
  File "django/db/models/sql/query.py", line 241, in sql_with_params
    return self.get_compiler(DEFAULT_DB_ALIAS).as_sql()
  File "django/db/models/sql/compiler.py", line 441, in as_sql
    where, w_params = self.compile(self.where) if self.where is not None else ("", [])
  File "django/db/models/sql/compiler.py", line 373, in compile
    sql, params = node.as_sql(self, self.connection)
  File "django/db/models/sql/where.py", line 97, in as_sql
    raise EmptyResultSet
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `kolibri/core/content/utils/search.py`
Content:
```
1 """
2 Avoiding direct model imports in here so that we can import these functions into places
3 that should not initiate the Django app registry.
4 """
5 import hashlib
6 
7 try:
8     from django.contrib.postgres.aggregates import BitOr
9 except ImportError:
10     BitOr = None
11 
12 from django.db import connections
13 from django.db.models import Aggregate
14 from django.db.models import Case
15 from django.db.models import Value
16 from django.db.models import When
17 from django.db.models.fields import IntegerField
18 from le_utils.constants.labels.accessibility_categories import (
19     ACCESSIBILITYCATEGORIESLIST,
20 )
21 from le_utils.constants.labels.learning_activities import LEARNINGACTIVITIESLIST
22 from le_utils.constants.labels.levels import LEVELSLIST
23 from le_utils.constants.labels.needs import NEEDSLIST
24 from le_utils.constants.labels.subjects import SUBJECTSLIST
25 
26 from kolibri.core.utils.cache import process_cache as cache
27 
28 
29 metadata_lookup = {
30     "learning_activities": LEARNINGACTIVITIESLIST,
31     "categories": SUBJECTSLIST,
32     "grade_levels": LEVELSLIST,
33     "accessibility_labels": ACCESSIBILITYCATEGORIESLIST,
34     "learner_needs": NEEDSLIST,
35 }
36 
37 
38 metadata_bitmasks = {}
39 
40 bitmask_fieldnames = {}
41 
42 
43 for key, labels in metadata_lookup.items():
44     bitmask_lookup = {}
45     i = 0
46     while labels[i : i + 64]:
47         bitmask_field_name = "{}_bitmask_{}".format(key, i)
48         bitmask_fieldnames[bitmask_field_name] = []
49         for j, label in enumerate(labels):
50             info = {
51                 "bitmask_field_name": bitmask_field_name,
52                 "field_name": key,
53                 "bits": 2 ** j,
54                 "label": label,
55             }
56             bitmask_lookup[label] = info
57             bitmask_fieldnames[bitmask_field_name].append(info)
58         i += 64
59     metadata_bitmasks[key] = bitmask_lookup
60 
61 
62 def _get_available_languages(base_queryset):
63     from kolibri.core.content.models import Language
64 
65     langs = Language.objects.filter(
66         id__in=base_queryset.exclude(lang=None)
67         .values_list("lang_id", flat=True)
68         .distinct()
69     ).values("id", "lang_name")
70     return list(langs)
71 
72 
73 def _get_available_channels(base_queryset):
74     from kolibri.core.content.models import ChannelMetadata
75 
76     return list(
77         ChannelMetadata.objects.filter(
78             id__in=base_queryset.values_list("channel_id", flat=True).distinct()
79         ).values("id", "name")
80     )
81 
82 
83 class SQLiteBitwiseORAggregate(Aggregate):
84     name = "BitwiseOR"
85 
86     def __init__(self, expression, num_bits=None, **extra):
87         if not num_bits:
88             raise ValueError("num_bits must be a positive integer")
89         self.num_bits = num_bits
90         super(SQLiteBitwiseORAggregate, self).__init__(
91             expression, output_field=IntegerField(), **extra
92         )
93 
94     @property
95     def template(self):
96         return " + ".join(
97             "max(%(expressions)s&{})".format(2 ** i) for i in range(0, self.num_bits)
98         )
99 
100 
101 def get_available_metadata_labels(base_queryset):
102     from kolibri.core.device.models import ContentCacheKey
103 
104     content_cache_key = ContentCacheKey.get_cache_key()
105     cache_key = "search-labels:{}:{}".format(
106         content_cache_key,
107         hashlib.md5(str(base_queryset.query).encode("utf8")).hexdigest(),
108     )
109     if cache_key not in cache:
110         base_queryset = base_queryset.order_by()
111         aggregates = {}
112         for field in bitmask_fieldnames:
113             field_agg = field + "_agg"
114             if connections[base_queryset.db].vendor == "sqlite" or BitOr is None:
115                 aggregates[field_agg] = SQLiteBitwiseORAggregate(
116                     field, num_bits=len(bitmask_fieldnames[field])
117                 )
118             elif connections[base_queryset.db].vendor == "postgresql":
119                 aggregates[field_agg] = BitOr(field)
120         output = {}
121         agg = base_queryset.aggregate(**aggregates)
122         for field, values in bitmask_fieldnames.items():
123             bit_value = agg[field + "_agg"]
124             for value in values:
125                 if value["field_name"] not in output:
126                     output[value["field_name"]] = []
127                 if bit_value is not None and bit_value & value["bits"]:
128                     output[value["field_name"]].append(value["label"])
129         output["languages"] = _get_available_languages(base_queryset)
130         output["channels"] = _get_available_channels(base_queryset)
131         cache.set(cache_key, output, timeout=None)
132     return cache.get(cache_key)
133 
134 
135 def get_all_contentnode_label_metadata():
136     from kolibri.core.content.models import ContentNode
137 
138     return get_available_metadata_labels(ContentNode.objects.filter(available=True))
139 
140 
141 def annotate_label_bitmasks(queryset):
142     update_statements = {}
143     for bitmask_fieldname, label_info in bitmask_fieldnames.items():
144         update_statements[bitmask_fieldname] = sum(
145             Case(
146                 When(
147                     **{
148                         info["field_name"] + "__contains": info["label"],
149                         "then": Value(info["bits"]),
150                     }
151                 ),
152                 default=Value(0),
153             )
154             for info in label_info
155         )
156     queryset.update(**update_statements)
157
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/kolibri/core/content/utils/search.py b/kolibri/core/content/utils/search.py
--- a/kolibri/core/content/utils/search.py
+++ b/kolibri/core/content/utils/search.py
@@ -9,6 +9,7 @@
 except ImportError:
     BitOr = None
 
+from django.core.exceptions import EmptyResultSet
 from django.db import connections
 from django.db.models import Aggregate
 from django.db.models import Case
@@ -39,6 +40,11 @@
 
 bitmask_fieldnames = {}
 
+empty_labels = {
+    "languages": [],
+    "channels": [],
+}
+
 
 for key, labels in metadata_lookup.items():
     bitmask_lookup = {}
@@ -57,6 +63,7 @@
             bitmask_fieldnames[bitmask_field_name].append(info)
         i += 64
     metadata_bitmasks[key] = bitmask_lookup
+    empty_labels[key] = []
 
 
 def _get_available_languages(base_queryset):
@@ -98,14 +105,17 @@
         )
 
 
-def get_available_metadata_labels(base_queryset):
+def get_available_metadata_labels(base_queryset):  # noqa: C901
     from kolibri.core.device.models import ContentCacheKey
 
     content_cache_key = ContentCacheKey.get_cache_key()
-    cache_key = "search-labels:{}:{}".format(
-        content_cache_key,
-        hashlib.md5(str(base_queryset.query).encode("utf8")).hexdigest(),
-    )
+    try:
+        cache_key = "search-labels:{}:{}".format(
+            content_cache_key,
+            hashlib.md5(str(base_queryset.query).encode("utf8")).hexdigest(),
+        )
+    except EmptyResultSet:
+        return empty_labels
     if cache_key not in cache:
         base_queryset = base_queryset.order_by()
         aggregates = {}

{"golden_diff": "diff --git a/kolibri/core/content/utils/search.py b/kolibri/core/content/utils/search.py\n--- a/kolibri/core/content/utils/search.py\n+++ b/kolibri/core/content/utils/search.py\n@@ -9,6 +9,7 @@\n except ImportError:\n     BitOr = None\n \n+from django.core.exceptions import EmptyResultSet\n from django.db import connections\n from django.db.models import Aggregate\n from django.db.models import Case\n@@ -39,6 +40,11 @@\n \n bitmask_fieldnames = {}\n \n+empty_labels = {\n+    \"languages\": [],\n+    \"channels\": [],\n+}\n+\n \n for key, labels in metadata_lookup.items():\n     bitmask_lookup = {}\n@@ -57,6 +63,7 @@\n             bitmask_fieldnames[bitmask_field_name].append(info)\n         i += 64\n     metadata_bitmasks[key] = bitmask_lookup\n+    empty_labels[key] = []\n \n \n def _get_available_languages(base_queryset):\n@@ -98,14 +105,17 @@\n         )\n \n \n-def get_available_metadata_labels(base_queryset):\n+def get_available_metadata_labels(base_queryset):  # noqa: C901\n     from kolibri.core.device.models import ContentCacheKey\n \n     content_cache_key = ContentCacheKey.get_cache_key()\n-    cache_key = \"search-labels:{}:{}\".format(\n-        content_cache_key,\n-        hashlib.md5(str(base_queryset.query).encode(\"utf8\")).hexdigest(),\n-    )\n+    try:\n+        cache_key = \"search-labels:{}:{}\".format(\n+            content_cache_key,\n+            hashlib.md5(str(base_queryset.query).encode(\"utf8\")).hexdigest(),\n+        )\n+    except EmptyResultSet:\n+        return empty_labels\n     if cache_key not in cache:\n         base_queryset = base_queryset.order_by()\n         aggregates = {}\n", "issue": "Catch and handle EmptyResultSet error when trying to cache metadata labels\nEmptyResultSet\n\nSentry Issue: [KOLIBRI-BACKEND-2E9](https://learningequality.sentry.io/issues/4005137733/?referrer=github_integration)\n\n```\nEmptyResultSet: \n(16 additional frame(s) were not displayed)\n...\n  File \"django/db/models/sql/query.py\", line 233, in __str__\n    sql, params = self.sql_with_params()\n  File \"django/db/models/sql/query.py\", line 241, in sql_with_params\n    return self.get_compiler(DEFAULT_DB_ALIAS).as_sql()\n  File \"django/db/models/sql/compiler.py\", line 441, in as_sql\n    where, w_params = self.compile(self.where) if self.where is not None else (\"\", [])\n  File \"django/db/models/sql/compiler.py\", line 373, in compile\n    sql, params = node.as_sql(self, self.connection)\n  File \"django/db/models/sql/where.py\", line 97, in as_sql\n    raise EmptyResultSet\n```\n", "before_files": [{"content": "\"\"\"\nAvoiding direct model imports in here so that we can import these functions into places\nthat should not initiate the Django app registry.\n\"\"\"\nimport hashlib\n\ntry:\n    from django.contrib.postgres.aggregates import BitOr\nexcept ImportError:\n    BitOr = None\n\nfrom django.db import connections\nfrom django.db.models import Aggregate\nfrom django.db.models import Case\nfrom django.db.models import Value\nfrom django.db.models import When\nfrom django.db.models.fields import IntegerField\nfrom le_utils.constants.labels.accessibility_categories import (\n    ACCESSIBILITYCATEGORIESLIST,\n)\nfrom le_utils.constants.labels.learning_activities import LEARNINGACTIVITIESLIST\nfrom le_utils.constants.labels.levels import LEVELSLIST\nfrom le_utils.constants.labels.needs import NEEDSLIST\nfrom le_utils.constants.labels.subjects import SUBJECTSLIST\n\nfrom kolibri.core.utils.cache import process_cache as cache\n\n\nmetadata_lookup = {\n    \"learning_activities\": LEARNINGACTIVITIESLIST,\n    \"categories\": SUBJECTSLIST,\n    \"grade_levels\": LEVELSLIST,\n    \"accessibility_labels\": ACCESSIBILITYCATEGORIESLIST,\n    \"learner_needs\": NEEDSLIST,\n}\n\n\nmetadata_bitmasks = {}\n\nbitmask_fieldnames = {}\n\n\nfor key, labels in metadata_lookup.items():\n    bitmask_lookup = {}\n    i = 0\n    while labels[i : i + 64]:\n        bitmask_field_name = \"{}_bitmask_{}\".format(key, i)\n        bitmask_fieldnames[bitmask_field_name] = []\n        for j, label in enumerate(labels):\n            info = {\n                \"bitmask_field_name\": bitmask_field_name,\n                \"field_name\": key,\n                \"bits\": 2 ** j,\n                \"label\": label,\n            }\n            bitmask_lookup[label] = info\n            bitmask_fieldnames[bitmask_field_name].append(info)\n        i += 64\n    metadata_bitmasks[key] = bitmask_lookup\n\n\ndef _get_available_languages(base_queryset):\n    from kolibri.core.content.models import Language\n\n    langs = Language.objects.filter(\n        id__in=base_queryset.exclude(lang=None)\n        .values_list(\"lang_id\", flat=True)\n        .distinct()\n    ).values(\"id\", \"lang_name\")\n    return list(langs)\n\n\ndef _get_available_channels(base_queryset):\n    from kolibri.core.content.models import ChannelMetadata\n\n    return list(\n        ChannelMetadata.objects.filter(\n            id__in=base_queryset.values_list(\"channel_id\", flat=True).distinct()\n        ).values(\"id\", \"name\")\n    )\n\n\nclass SQLiteBitwiseORAggregate(Aggregate):\n    name = \"BitwiseOR\"\n\n    def __init__(self, expression, num_bits=None, **extra):\n        if not num_bits:\n            raise ValueError(\"num_bits must be a positive integer\")\n        self.num_bits = num_bits\n        super(SQLiteBitwiseORAggregate, self).__init__(\n            expression, output_field=IntegerField(), **extra\n        )\n\n    @property\n    def template(self):\n        return \" + \".join(\n            \"max(%(expressions)s&{})\".format(2 ** i) for i in range(0, self.num_bits)\n        )\n\n\ndef get_available_metadata_labels(base_queryset):\n    from kolibri.core.device.models import ContentCacheKey\n\n    content_cache_key = ContentCacheKey.get_cache_key()\n    cache_key = \"search-labels:{}:{}\".format(\n        content_cache_key,\n        hashlib.md5(str(base_queryset.query).encode(\"utf8\")).hexdigest(),\n    )\n    if cache_key not in cache:\n        base_queryset = base_queryset.order_by()\n        aggregates = {}\n        for field in bitmask_fieldnames:\n            field_agg = field + \"_agg\"\n            if connections[base_queryset.db].vendor == \"sqlite\" or BitOr is None:\n                aggregates[field_agg] = SQLiteBitwiseORAggregate(\n                    field, num_bits=len(bitmask_fieldnames[field])\n                )\n            elif connections[base_queryset.db].vendor == \"postgresql\":\n                aggregates[field_agg] = BitOr(field)\n        output = {}\n        agg = base_queryset.aggregate(**aggregates)\n        for field, values in bitmask_fieldnames.items():\n            bit_value = agg[field + \"_agg\"]\n            for value in values:\n                if value[\"field_name\"] not in output:\n                    output[value[\"field_name\"]] = []\n                if bit_value is not None and bit_value & value[\"bits\"]:\n                    output[value[\"field_name\"]].append(value[\"label\"])\n        output[\"languages\"] = _get_available_languages(base_queryset)\n        output[\"channels\"] = _get_available_channels(base_queryset)\n        cache.set(cache_key, output, timeout=None)\n    return cache.get(cache_key)\n\n\ndef get_all_contentnode_label_metadata():\n    from kolibri.core.content.models import ContentNode\n\n    return get_available_metadata_labels(ContentNode.objects.filter(available=True))\n\n\ndef annotate_label_bitmasks(queryset):\n    update_statements = {}\n    for bitmask_fieldname, label_info in bitmask_fieldnames.items():\n        update_statements[bitmask_fieldname] = sum(\n            Case(\n                When(\n                    **{\n                        info[\"field_name\"] + \"__contains\": info[\"label\"],\n                        \"then\": Value(info[\"bits\"]),\n                    }\n                ),\n                default=Value(0),\n            )\n            for info in label_info\n        )\n    queryset.update(**update_statements)\n", "path": "kolibri/core/content/utils/search.py"}], "after_files": [{"content": "\"\"\"\nAvoiding direct model imports in here so that we can import these functions into places\nthat should not initiate the Django app registry.\n\"\"\"\nimport hashlib\n\ntry:\n    from django.contrib.postgres.aggregates import BitOr\nexcept ImportError:\n    BitOr = None\n\nfrom django.core.exceptions import EmptyResultSet\nfrom django.db import connections\nfrom django.db.models import Aggregate\nfrom django.db.models import Case\nfrom django.db.models import Value\nfrom django.db.models import When\nfrom django.db.models.fields import IntegerField\nfrom le_utils.constants.labels.accessibility_categories import (\n    ACCESSIBILITYCATEGORIESLIST,\n)\nfrom le_utils.constants.labels.learning_activities import LEARNINGACTIVITIESLIST\nfrom le_utils.constants.labels.levels import LEVELSLIST\nfrom le_utils.constants.labels.needs import NEEDSLIST\nfrom le_utils.constants.labels.subjects import SUBJECTSLIST\n\nfrom kolibri.core.utils.cache import process_cache as cache\n\n\nmetadata_lookup = {\n    \"learning_activities\": LEARNINGACTIVITIESLIST,\n    \"categories\": SUBJECTSLIST,\n    \"grade_levels\": LEVELSLIST,\n    \"accessibility_labels\": ACCESSIBILITYCATEGORIESLIST,\n    \"learner_needs\": NEEDSLIST,\n}\n\n\nmetadata_bitmasks = {}\n\nbitmask_fieldnames = {}\n\nempty_labels = {\n    \"languages\": [],\n    \"channels\": [],\n}\n\n\nfor key, labels in metadata_lookup.items():\n    bitmask_lookup = {}\n    i = 0\n    while labels[i : i + 64]:\n        bitmask_field_name = \"{}_bitmask_{}\".format(key, i)\n        bitmask_fieldnames[bitmask_field_name] = []\n        for j, label in enumerate(labels):\n            info = {\n                \"bitmask_field_name\": bitmask_field_name,\n                \"field_name\": key,\n                \"bits\": 2 ** j,\n                \"label\": label,\n            }\n            bitmask_lookup[label] = info\n            bitmask_fieldnames[bitmask_field_name].append(info)\n        i += 64\n    metadata_bitmasks[key] = bitmask_lookup\n    empty_labels[key] = []\n\n\ndef _get_available_languages(base_queryset):\n    from kolibri.core.content.models import Language\n\n    langs = Language.objects.filter(\n        id__in=base_queryset.exclude(lang=None)\n        .values_list(\"lang_id\", flat=True)\n        .distinct()\n    ).values(\"id\", \"lang_name\")\n    return list(langs)\n\n\ndef _get_available_channels(base_queryset):\n    from kolibri.core.content.models import ChannelMetadata\n\n    return list(\n        ChannelMetadata.objects.filter(\n            id__in=base_queryset.values_list(\"channel_id\", flat=True).distinct()\n        ).values(\"id\", \"name\")\n    )\n\n\nclass SQLiteBitwiseORAggregate(Aggregate):\n    name = \"BitwiseOR\"\n\n    def __init__(self, expression, num_bits=None, **extra):\n        if not num_bits:\n            raise ValueError(\"num_bits must be a positive integer\")\n        self.num_bits = num_bits\n        super(SQLiteBitwiseORAggregate, self).__init__(\n            expression, output_field=IntegerField(), **extra\n        )\n\n    @property\n    def template(self):\n        return \" + \".join(\n            \"max(%(expressions)s&{})\".format(2 ** i) for i in range(0, self.num_bits)\n        )\n\n\ndef get_available_metadata_labels(base_queryset):  # noqa: C901\n    from kolibri.core.device.models import ContentCacheKey\n\n    content_cache_key = ContentCacheKey.get_cache_key()\n    try:\n        cache_key = \"search-labels:{}:{}\".format(\n            content_cache_key,\n            hashlib.md5(str(base_queryset.query).encode(\"utf8\")).hexdigest(),\n        )\n    except EmptyResultSet:\n        return empty_labels\n    if cache_key not in cache:\n        base_queryset = base_queryset.order_by()\n        aggregates = {}\n        for field in bitmask_fieldnames:\n            field_agg = field + \"_agg\"\n            if connections[base_queryset.db].vendor == \"sqlite\" or BitOr is None:\n                aggregates[field_agg] = SQLiteBitwiseORAggregate(\n                    field, num_bits=len(bitmask_fieldnames[field])\n                )\n            elif connections[base_queryset.db].vendor == \"postgresql\":\n                aggregates[field_agg] = BitOr(field)\n        output = {}\n        agg = base_queryset.aggregate(**aggregates)\n        for field, values in bitmask_fieldnames.items():\n            bit_value = agg[field + \"_agg\"]\n            for value in values:\n                if value[\"field_name\"] not in output:\n                    output[value[\"field_name\"]] = []\n                if bit_value is not None and bit_value & value[\"bits\"]:\n                    output[value[\"field_name\"]].append(value[\"label\"])\n        output[\"languages\"] = _get_available_languages(base_queryset)\n        output[\"channels\"] = _get_available_channels(base_queryset)\n        cache.set(cache_key, output, timeout=None)\n    return cache.get(cache_key)\n\n\ndef get_all_contentnode_label_metadata():\n    from kolibri.core.content.models import ContentNode\n\n    return get_available_metadata_labels(ContentNode.objects.filter(available=True))\n\n\ndef annotate_label_bitmasks(queryset):\n    update_statements = {}\n    for bitmask_fieldname, label_info in bitmask_fieldnames.items():\n        update_statements[bitmask_fieldname] = sum(\n            Case(\n                When(\n                    **{\n                        info[\"field_name\"] + \"__contains\": info[\"label\"],\n                        \"then\": Value(info[\"bits\"]),\n                    }\n                ),\n                default=Value(0),\n            )\n            for info in label_info\n        )\n    queryset.update(**update_statements)\n", "path": "kolibri/core/content/utils/search.py"}]}