We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
'message' referenced before assignment in recipe_helpers.validate_recipe
https://github.com/google/turbinia/blob/a756f4c625cf3796fc82d160f3c794c7e2039437/turbinia/lib/recipe_helpers.py#L169

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `turbinia/lib/recipe_helpers.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 # Copyright 2021 Google Inc.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #      http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 """Library to contain recipe validation logic."""
16 
17 import copy
18 import logging
19 import yaml
20 import os
21 
22 from yaml import Loader
23 from yaml import load
24 from turbinia import config
25 from turbinia.lib.file_helpers import file_to_str
26 from turbinia.lib.file_helpers import file_to_list
27 from turbinia.task_utils import TaskLoader
28 
29 log = logging.getLogger('turbinia')
30 
31 #Attributes allowed on the 'globals' task recipe
32 DEFAULT_GLOBALS_RECIPE = {
33     'debug_tasks': False,
34     'jobs_allowlist': [],
35     'jobs_denylist': [],
36     'yara_rules': '',
37     'filter_patterns': [],
38     'sketch_id': None,
39     'group_id': ''
40 }
41 
42 #Default recipes dict
43 DEFAULT_RECIPE = {'globals': DEFAULT_GLOBALS_RECIPE}
44 
45 
46 def load_recipe_from_file(recipe_file, validate=True):
47   """Load recipe from file.
48 
49   Args:
50     recipe_file(str): Name of the recipe file to be read.
51 
52   Returns:
53     dict: Validated and corrected recipe dictionary.
54         Empty dict if recipe is invalid.
55   """
56   if not recipe_file:
57     return copy.deepcopy(DEFAULT_RECIPE)
58   try:
59     log.info('Loading recipe file from {0:s}'.format(recipe_file))
60     with open(recipe_file, 'r') as r_file:
61       recipe_file_contents = r_file.read()
62       recipe_dict = load(recipe_file_contents, Loader=Loader)
63       if validate:
64         success, _ = validate_recipe(recipe_dict)
65         if success:
66           return recipe_dict
67       else:
68         return recipe_dict
69   except yaml.parser.ParserError as exception:
70     message = (
71         'Invalid YAML on recipe file {0:s}: {1!s}.'.format(
72             recipe_file, exception))
73     log.error(message)
74   except IOError as exception:
75     log.error(
76         'Failed to read recipe file {0:s}: {1!s}'.format(
77             recipe_file, exception))
78   return {}
79 
80 
81 def validate_globals_recipe(proposed_globals_recipe):
82   """Validate the 'globals' special task recipe.
83 
84   Args:
85     proposed_globals_recipe(dict): globals task recipe in need of validation.
86 
87   Returns:
88     Tuple(
89       bool: Whether the recipe has a valid format.
90       str: Error message if validation failed.
91     )
92   """
93   reference_globals_recipe = copy.deepcopy(DEFAULT_GLOBALS_RECIPE)
94   reference_globals_recipe.update(proposed_globals_recipe)
95 
96   filter_patterns_file = proposed_globals_recipe.get(
97       'filter_patterns_file', None)
98   yara_rules_file = proposed_globals_recipe.get('yara_rules_file', None)
99   if filter_patterns_file:
100     proposed_globals_recipe['filter_patterns'] = file_to_list(
101         filter_patterns_file)
102   if yara_rules_file:
103     proposed_globals_recipe['yara_rules'] = file_to_str(yara_rules_file)
104   diff = set(proposed_globals_recipe) - set(DEFAULT_GLOBALS_RECIPE)
105   if diff:
106     message = (
107         'Invalid recipe: Unknown keys [{0:s}] found in globals recipe'.format(
108             str(diff)))
109     log.error(message)
110     return (False, message)
111 
112   if (proposed_globals_recipe.get('jobs_allowlist') and
113       proposed_globals_recipe.get('jobs_denylist')):
114     message = 'Invalid recipe: Jobs cannot be in both the allow and deny lists'
115     log.error(message)
116     return (False, message)
117   return (True, '')
118 
119 
120 def validate_recipe(recipe_dict):
121   """Validate the 'recipe' dict supplied by the request recipe.
122 
123   Args:
124     recipe_dict(dict): Turbinia recipe in need of validation
125     submitted along with the evidence.
126 
127   Returns:
128     Tuple(
129       bool: Whether the recipe has a valid format.
130       str: Error message if validation failed.
131     )
132   """
133   tasks_with_recipe = []
134   #If not globals task recipe is specified create one.
135   if 'globals' not in recipe_dict:
136     recipe_dict['globals'] = copy.deepcopy(DEFAULT_RECIPE)
137     log.warning(
138         'No globals recipe specified, all recipes should include '
139         'a globals entry, the default values will be used')
140   else:
141     success, message = validate_globals_recipe(recipe_dict['globals'])
142     if not success:
143       log.error(message)
144       return (False, message)
145 
146   for recipe_item, recipe_item_contents in recipe_dict.items():
147     if recipe_item in tasks_with_recipe:
148       message = (
149           'Two recipe items with the same name \"{0:s}\" have been found. '
150           'If you wish to specify several task runs of the same tool, '
151           'please include them in separate recipes.'.format(recipe_item))
152       log.error(message)
153       return (False, message)
154     if recipe_item != 'globals':
155       if 'task' not in recipe_item_contents:
156         message = (
157             'Recipe item \"{0:s}\" has no "task" key. All recipe items '
158             'must have a "task" key indicating the TurbiniaTask '
159             'to which it relates.'.format(recipe_item))
160         log.error(message)
161         return (False, message)
162       proposed_task = recipe_item_contents['task']
163 
164       task_loader = TaskLoader()
165       if not task_loader.check_task_name(proposed_task):
166         log.error(
167             'Task {0:s} defined for task recipe {1:s} does not exist.'.format(
168                 proposed_task, recipe_item))
169         return (False, message)
170       tasks_with_recipe.append(recipe_item)
171 
172   return (True, '')
173 
174 
175 def get_recipe_path_from_name(recipe_name):
176   """Returns a recipe's path from a recipe name.
177 
178   Args:
179     recipe_name (str): A recipe name.
180 
181   Returns:
182     str: a recipe's file system path.
183   """
184   recipe_path = ''
185   if not recipe_name.endswith('.yaml'):
186     recipe_name = recipe_name + '.yaml'
187 
188   if hasattr(config, 'RECIPE_FILE_DIR') and config.RECIPE_FILE_DIR:
189     recipe_path = os.path.join(config.RECIPE_FILE_DIR, recipe_name)
190   else:
191     recipe_path = os.path.realpath(__file__)
192     recipe_path = os.path.dirname(recipe_path)
193     recipe_path = os.path.join(recipe_path, 'config', 'recipes')
194     recipe_path = os.path.join(recipe_path, recipe_name)
195 
196   return recipe_path
197
```
--- 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/turbinia/lib/recipe_helpers.py b/turbinia/lib/recipe_helpers.py
--- a/turbinia/lib/recipe_helpers.py
+++ b/turbinia/lib/recipe_helpers.py
@@ -163,9 +163,10 @@
 
       task_loader = TaskLoader()
       if not task_loader.check_task_name(proposed_task):
-        log.error(
-            'Task {0:s} defined for task recipe {1:s} does not exist.'.format(
-                proposed_task, recipe_item))
+        message = (
+            'Task {0:s} defined for task recipe {1:s} does not '
+            'exist.'.format(proposed_task, recipe_item))
+        log.error(message)
         return (False, message)
       tasks_with_recipe.append(recipe_item)

{"golden_diff": "diff --git a/turbinia/lib/recipe_helpers.py b/turbinia/lib/recipe_helpers.py\n--- a/turbinia/lib/recipe_helpers.py\n+++ b/turbinia/lib/recipe_helpers.py\n@@ -163,9 +163,10 @@\n \n       task_loader = TaskLoader()\n       if not task_loader.check_task_name(proposed_task):\n-        log.error(\n-            'Task {0:s} defined for task recipe {1:s} does not exist.'.format(\n-                proposed_task, recipe_item))\n+        message = (\n+            'Task {0:s} defined for task recipe {1:s} does not '\n+            'exist.'.format(proposed_task, recipe_item))\n+        log.error(message)\n         return (False, message)\n       tasks_with_recipe.append(recipe_item)\n", "issue": "'message' referenced before assignment in recipe_helpers.validate_recipe\nhttps://github.com/google/turbinia/blob/a756f4c625cf3796fc82d160f3c794c7e2039437/turbinia/lib/recipe_helpers.py#L169\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2021 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Library to contain recipe validation logic.\"\"\"\n\nimport copy\nimport logging\nimport yaml\nimport os\n\nfrom yaml import Loader\nfrom yaml import load\nfrom turbinia import config\nfrom turbinia.lib.file_helpers import file_to_str\nfrom turbinia.lib.file_helpers import file_to_list\nfrom turbinia.task_utils import TaskLoader\n\nlog = logging.getLogger('turbinia')\n\n#Attributes allowed on the 'globals' task recipe\nDEFAULT_GLOBALS_RECIPE = {\n    'debug_tasks': False,\n    'jobs_allowlist': [],\n    'jobs_denylist': [],\n    'yara_rules': '',\n    'filter_patterns': [],\n    'sketch_id': None,\n    'group_id': ''\n}\n\n#Default recipes dict\nDEFAULT_RECIPE = {'globals': DEFAULT_GLOBALS_RECIPE}\n\n\ndef load_recipe_from_file(recipe_file, validate=True):\n  \"\"\"Load recipe from file.\n\n  Args:\n    recipe_file(str): Name of the recipe file to be read.\n\n  Returns:\n    dict: Validated and corrected recipe dictionary.\n        Empty dict if recipe is invalid.\n  \"\"\"\n  if not recipe_file:\n    return copy.deepcopy(DEFAULT_RECIPE)\n  try:\n    log.info('Loading recipe file from {0:s}'.format(recipe_file))\n    with open(recipe_file, 'r') as r_file:\n      recipe_file_contents = r_file.read()\n      recipe_dict = load(recipe_file_contents, Loader=Loader)\n      if validate:\n        success, _ = validate_recipe(recipe_dict)\n        if success:\n          return recipe_dict\n      else:\n        return recipe_dict\n  except yaml.parser.ParserError as exception:\n    message = (\n        'Invalid YAML on recipe file {0:s}: {1!s}.'.format(\n            recipe_file, exception))\n    log.error(message)\n  except IOError as exception:\n    log.error(\n        'Failed to read recipe file {0:s}: {1!s}'.format(\n            recipe_file, exception))\n  return {}\n\n\ndef validate_globals_recipe(proposed_globals_recipe):\n  \"\"\"Validate the 'globals' special task recipe.\n\n  Args:\n    proposed_globals_recipe(dict): globals task recipe in need of validation.\n\n  Returns:\n    Tuple(\n      bool: Whether the recipe has a valid format.\n      str: Error message if validation failed.\n    )\n  \"\"\"\n  reference_globals_recipe = copy.deepcopy(DEFAULT_GLOBALS_RECIPE)\n  reference_globals_recipe.update(proposed_globals_recipe)\n\n  filter_patterns_file = proposed_globals_recipe.get(\n      'filter_patterns_file', None)\n  yara_rules_file = proposed_globals_recipe.get('yara_rules_file', None)\n  if filter_patterns_file:\n    proposed_globals_recipe['filter_patterns'] = file_to_list(\n        filter_patterns_file)\n  if yara_rules_file:\n    proposed_globals_recipe['yara_rules'] = file_to_str(yara_rules_file)\n  diff = set(proposed_globals_recipe) - set(DEFAULT_GLOBALS_RECIPE)\n  if diff:\n    message = (\n        'Invalid recipe: Unknown keys [{0:s}] found in globals recipe'.format(\n            str(diff)))\n    log.error(message)\n    return (False, message)\n\n  if (proposed_globals_recipe.get('jobs_allowlist') and\n      proposed_globals_recipe.get('jobs_denylist')):\n    message = 'Invalid recipe: Jobs cannot be in both the allow and deny lists'\n    log.error(message)\n    return (False, message)\n  return (True, '')\n\n\ndef validate_recipe(recipe_dict):\n  \"\"\"Validate the 'recipe' dict supplied by the request recipe.\n\n  Args:\n    recipe_dict(dict): Turbinia recipe in need of validation\n    submitted along with the evidence.\n\n  Returns:\n    Tuple(\n      bool: Whether the recipe has a valid format.\n      str: Error message if validation failed.\n    )\n  \"\"\"\n  tasks_with_recipe = []\n  #If not globals task recipe is specified create one.\n  if 'globals' not in recipe_dict:\n    recipe_dict['globals'] = copy.deepcopy(DEFAULT_RECIPE)\n    log.warning(\n        'No globals recipe specified, all recipes should include '\n        'a globals entry, the default values will be used')\n  else:\n    success, message = validate_globals_recipe(recipe_dict['globals'])\n    if not success:\n      log.error(message)\n      return (False, message)\n\n  for recipe_item, recipe_item_contents in recipe_dict.items():\n    if recipe_item in tasks_with_recipe:\n      message = (\n          'Two recipe items with the same name \\\"{0:s}\\\" have been found. '\n          'If you wish to specify several task runs of the same tool, '\n          'please include them in separate recipes.'.format(recipe_item))\n      log.error(message)\n      return (False, message)\n    if recipe_item != 'globals':\n      if 'task' not in recipe_item_contents:\n        message = (\n            'Recipe item \\\"{0:s}\\\" has no \"task\" key. All recipe items '\n            'must have a \"task\" key indicating the TurbiniaTask '\n            'to which it relates.'.format(recipe_item))\n        log.error(message)\n        return (False, message)\n      proposed_task = recipe_item_contents['task']\n\n      task_loader = TaskLoader()\n      if not task_loader.check_task_name(proposed_task):\n        log.error(\n            'Task {0:s} defined for task recipe {1:s} does not exist.'.format(\n                proposed_task, recipe_item))\n        return (False, message)\n      tasks_with_recipe.append(recipe_item)\n\n  return (True, '')\n\n\ndef get_recipe_path_from_name(recipe_name):\n  \"\"\"Returns a recipe's path from a recipe name.\n\n  Args:\n    recipe_name (str): A recipe name.\n\n  Returns:\n    str: a recipe's file system path.\n  \"\"\"\n  recipe_path = ''\n  if not recipe_name.endswith('.yaml'):\n    recipe_name = recipe_name + '.yaml'\n\n  if hasattr(config, 'RECIPE_FILE_DIR') and config.RECIPE_FILE_DIR:\n    recipe_path = os.path.join(config.RECIPE_FILE_DIR, recipe_name)\n  else:\n    recipe_path = os.path.realpath(__file__)\n    recipe_path = os.path.dirname(recipe_path)\n    recipe_path = os.path.join(recipe_path, 'config', 'recipes')\n    recipe_path = os.path.join(recipe_path, recipe_name)\n\n  return recipe_path\n", "path": "turbinia/lib/recipe_helpers.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright 2021 Google Inc.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\"\"\"Library to contain recipe validation logic.\"\"\"\n\nimport copy\nimport logging\nimport yaml\nimport os\n\nfrom yaml import Loader\nfrom yaml import load\nfrom turbinia import config\nfrom turbinia.lib.file_helpers import file_to_str\nfrom turbinia.lib.file_helpers import file_to_list\nfrom turbinia.task_utils import TaskLoader\n\nlog = logging.getLogger('turbinia')\n\n#Attributes allowed on the 'globals' task recipe\nDEFAULT_GLOBALS_RECIPE = {\n    'debug_tasks': False,\n    'jobs_allowlist': [],\n    'jobs_denylist': [],\n    'yara_rules': '',\n    'filter_patterns': [],\n    'sketch_id': None,\n    'group_id': ''\n}\n\n#Default recipes dict\nDEFAULT_RECIPE = {'globals': DEFAULT_GLOBALS_RECIPE}\n\n\ndef load_recipe_from_file(recipe_file, validate=True):\n  \"\"\"Load recipe from file.\n\n  Args:\n    recipe_file(str): Name of the recipe file to be read.\n\n  Returns:\n    dict: Validated and corrected recipe dictionary.\n        Empty dict if recipe is invalid.\n  \"\"\"\n  if not recipe_file:\n    return copy.deepcopy(DEFAULT_RECIPE)\n  try:\n    log.info('Loading recipe file from {0:s}'.format(recipe_file))\n    with open(recipe_file, 'r') as r_file:\n      recipe_file_contents = r_file.read()\n      recipe_dict = load(recipe_file_contents, Loader=Loader)\n      if validate:\n        success, _ = validate_recipe(recipe_dict)\n        if success:\n          return recipe_dict\n      else:\n        return recipe_dict\n  except yaml.parser.ParserError as exception:\n    message = (\n        'Invalid YAML on recipe file {0:s}: {1!s}.'.format(\n            recipe_file, exception))\n    log.error(message)\n  except IOError as exception:\n    log.error(\n        'Failed to read recipe file {0:s}: {1!s}'.format(\n            recipe_file, exception))\n  return {}\n\n\ndef validate_globals_recipe(proposed_globals_recipe):\n  \"\"\"Validate the 'globals' special task recipe.\n\n  Args:\n    proposed_globals_recipe(dict): globals task recipe in need of validation.\n\n  Returns:\n    Tuple(\n      bool: Whether the recipe has a valid format.\n      str: Error message if validation failed.\n    )\n  \"\"\"\n  reference_globals_recipe = copy.deepcopy(DEFAULT_GLOBALS_RECIPE)\n  reference_globals_recipe.update(proposed_globals_recipe)\n\n  filter_patterns_file = proposed_globals_recipe.get(\n      'filter_patterns_file', None)\n  yara_rules_file = proposed_globals_recipe.get('yara_rules_file', None)\n  if filter_patterns_file:\n    proposed_globals_recipe['filter_patterns'] = file_to_list(\n        filter_patterns_file)\n  if yara_rules_file:\n    proposed_globals_recipe['yara_rules'] = file_to_str(yara_rules_file)\n  diff = set(proposed_globals_recipe) - set(DEFAULT_GLOBALS_RECIPE)\n  if diff:\n    message = (\n        'Invalid recipe: Unknown keys [{0:s}] found in globals recipe'.format(\n            str(diff)))\n    log.error(message)\n    return (False, message)\n\n  if (proposed_globals_recipe.get('jobs_allowlist') and\n      proposed_globals_recipe.get('jobs_denylist')):\n    message = 'Invalid recipe: Jobs cannot be in both the allow and deny lists'\n    log.error(message)\n    return (False, message)\n  return (True, '')\n\n\ndef validate_recipe(recipe_dict):\n  \"\"\"Validate the 'recipe' dict supplied by the request recipe.\n\n  Args:\n    recipe_dict(dict): Turbinia recipe in need of validation\n    submitted along with the evidence.\n\n  Returns:\n    Tuple(\n      bool: Whether the recipe has a valid format.\n      str: Error message if validation failed.\n    )\n  \"\"\"\n  tasks_with_recipe = []\n  #If not globals task recipe is specified create one.\n  if 'globals' not in recipe_dict:\n    recipe_dict['globals'] = copy.deepcopy(DEFAULT_RECIPE)\n    log.warning(\n        'No globals recipe specified, all recipes should include '\n        'a globals entry, the default values will be used')\n  else:\n    success, message = validate_globals_recipe(recipe_dict['globals'])\n    if not success:\n      log.error(message)\n      return (False, message)\n\n  for recipe_item, recipe_item_contents in recipe_dict.items():\n    if recipe_item in tasks_with_recipe:\n      message = (\n          'Two recipe items with the same name \\\"{0:s}\\\" have been found. '\n          'If you wish to specify several task runs of the same tool, '\n          'please include them in separate recipes.'.format(recipe_item))\n      log.error(message)\n      return (False, message)\n    if recipe_item != 'globals':\n      if 'task' not in recipe_item_contents:\n        message = (\n            'Recipe item \\\"{0:s}\\\" has no \"task\" key. All recipe items '\n            'must have a \"task\" key indicating the TurbiniaTask '\n            'to which it relates.'.format(recipe_item))\n        log.error(message)\n        return (False, message)\n      proposed_task = recipe_item_contents['task']\n\n      task_loader = TaskLoader()\n      if not task_loader.check_task_name(proposed_task):\n        message = (\n            'Task {0:s} defined for task recipe {1:s} does not '\n            'exist.'.format(proposed_task, recipe_item))\n        log.error(message)\n        return (False, message)\n      tasks_with_recipe.append(recipe_item)\n\n  return (True, '')\n\n\ndef get_recipe_path_from_name(recipe_name):\n  \"\"\"Returns a recipe's path from a recipe name.\n\n  Args:\n    recipe_name (str): A recipe name.\n\n  Returns:\n    str: a recipe's file system path.\n  \"\"\"\n  recipe_path = ''\n  if not recipe_name.endswith('.yaml'):\n    recipe_name = recipe_name + '.yaml'\n\n  if hasattr(config, 'RECIPE_FILE_DIR') and config.RECIPE_FILE_DIR:\n    recipe_path = os.path.join(config.RECIPE_FILE_DIR, recipe_name)\n  else:\n    recipe_path = os.path.realpath(__file__)\n    recipe_path = os.path.dirname(recipe_path)\n    recipe_path = os.path.join(recipe_path, 'config', 'recipes')\n    recipe_path = os.path.join(recipe_path, recipe_name)\n\n  return recipe_path\n", "path": "turbinia/lib/recipe_helpers.py"}]}