Repository: searxng/searxng

Issue:
[Feature] Raise error when the engine doesn't exist
Raise an error when an engine doesn't exist and there is for example an old parameter that disabled a now removed engine.

See https://github.com/searxng/searxng/issues/1951#issuecomment-1324872496 for more info.

-----

<!-- PLEASE FILL THESE FIELDS, IT REALLY HELPS THE MAINTAINERS OF SearXNG -->

**Version of SearXNG, commit number if you are using on master branch and stipulate if you forked SearXNG**

Commit https://github.com/searxng/searxng/commit/3a765113eefc7ac0b1ee94e9a0ac0db8069ec336

**How did you install SearXNG?**
1. Git clone
2. pip install -r requirements.txt
3. `python -m searx.webapp`

**How To Reproduce**
Run searxng with this configuration:
```yaml
engines:
  - name: duckduckgo
    disabled: true
general:
  debug: true
server:
  secret_key: secret
use_default_settings: true
```

And you will get this error:
```
Traceback (most recent call last):
  File "/opt/python/latest/lib/python3.10/runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/opt/python/latest/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/workspaces/searx-custom/searxng2/searx/webapp.py", line 1390, in <module>
    search_initialize(enable_checker=True, check_network=True, enable_metrics=settings['general']['enable_metrics'])
  File "/workspaces/searx-custom/searxng2/searx/search/__init__.py", line 30, in initialize
    load_engines(settings_engines)
  File "/workspaces/searx-custom/searxng2/searx/engines/__init__.py", line 298, in load_engines
    engine = load_engine(engine_data)
  File "/workspaces/searx-custom/searxng2/searx/engines/__init__.py", line 121, in load_engine
    engine_module = engine_data['engine']
KeyError: 'engine'
```

**Expected behavior**
Searxng should work fine.

**Screenshots & Logs**
<!-- If applicable, add screenshots, logs to help explain your problem. -->

**Additional context**
<!-- Add any other context about the problem here. -->



Discussion:
Closing and maybe reopening later because it's probably an issue on my side.
Found the issue, it was due to:
```yaml
engines:
- disabled: true
  name: z-library
```
> Found the issue, it was due to:

Argh, that's a real pity and hard to trace issue .. z-library has been removed here:

https://github.com/searxng/searxng/pull/1937/files

but users will still have the engine entry in their `/etc/searxng/settings.yml`.

@dalf what do you think: is there way we parse the a [`use-default-settings`](https://docs.searxng.org/admin/engines/settings.html#use-default-settings) and raise warnings for engines not exists.

Renamed the title of the issue and switch this issue to a feature request. Reopening.

Resolving patch:
diff --git a/searx/engines/__init__.py b/searx/engines/__init__.py
--- a/searx/engines/__init__.py
+++ b/searx/engines/__init__.py
@@ -106,8 +106,12 @@ def load_engine(engine_data: dict) -> Optional[Engine]:
     - required attribute is not set :py:func:`is_missing_required_attributes`
 
     """
+    # pylint: disable=too-many-return-statements
 
-    engine_name = engine_data['name']
+    engine_name = engine_data.get('name')
+    if engine_name is None:
+        logger.error('An engine does not have a "name" field')
+        return None
     if '_' in engine_name:
         logger.error('Engine name contains underscore: "{}"'.format(engine_name))
         return None
@@ -118,7 +122,10 @@ def load_engine(engine_data: dict) -> Optional[Engine]:
         engine_data['name'] = engine_name
 
     # load_module
-    engine_module = engine_data['engine']
+    engine_module = engine_data.get('engine')
+    if engine_module is None:
+        logger.error('The "engine" field is missing for the engine named "{}"'.format(engine_name))
+        return None
     try:
         engine = load_module(engine_module + '.py', ENGINE_DIR)
     except (SyntaxError, KeyboardInterrupt, SystemExit, SystemError, ImportError, RuntimeError):


Test patch:
diff --git a/tests/unit/test_engines_init.py b/tests/unit/test_engines_init.py
--- a/tests/unit/test_engines_init.py
+++ b/tests/unit/test_engines_init.py
@@ -53,3 +53,25 @@ def test_initialize_engines_include_onions(self):
         self.assertIn('onions', engines.categories)
         self.assertIn('http://engine1.onion', engines.engines['engine1'].search_url)
         self.assertEqual(engines.engines['engine1'].timeout, 120.0)
+
+    def test_missing_name_field(self):
+        settings['outgoing']['using_tor_proxy'] = False
+        engine_list = [
+            {'engine': 'dummy', 'shortcut': 'e1', 'categories': 'general'},
+        ]
+        with self.assertLogs('searx.engines', level='ERROR') as cm:
+            engines.load_engines(engine_list)
+            self.assertEqual(len(engines.engines), 0)
+            self.assertEqual(cm.output, ['ERROR:searx.engines:An engine does not have a "name" field'])
+
+    def test_missing_engine_field(self):
+        settings['outgoing']['using_tor_proxy'] = False
+        engine_list = [
+            {'name': 'engine2', 'shortcut': 'e2', 'categories': 'onions'},
+        ]
+        with self.assertLogs('searx.engines', level='ERROR') as cm:
+            engines.load_engines(engine_list)
+            self.assertEqual(len(engines.engines), 0)
+            self.assertEqual(
+                cm.output, ['ERROR:searx.engines:The "engine" field is missing for the engine named "engine2"']
+            )