prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Error when using strict mode and multirun
  Modifying the `6_sweep` example to have `@hydra.main(config_path="conf/config.yaml", strict=True)` causes this error:
  
  ```python3
  6_sweep(master*)$ python3 experiment.py -m
  Traceback (most recent call last):
    File "experiment.py", line 15, in <module>
      experiment()
    File "/private/home/bda/repos/hydra/hydra/main.py", line 62, in decorated_main
      run_hydra(get_args(), task_function, config_path, strict)
    File "/private/home/bda/repos/hydra/hydra/_internal/utils.py", line 57, in run_hydra
      hydra.multirun(overrides=args.overrides)
    File "/private/home/bda/repos/hydra/hydra/_internal/hydra.py", line 124, in multirun
      return sweeper.sweep(arguments=task_overrides)
    File "/private/home/bda/repos/hydra/hydra/plugins/step_sweeper.py", line 63, in sweep
      results = self.launcher.launch(batch)
    File "/private/home/bda/repos/hydra/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py", line 67, in launch
      self.config.hydra.job.num_jobs = num_jobs
    File "/private/home/bda/anaconda3/lib/python3.7/site-packages/omegaconf-1.3.0-py3.7.egg/omegaconf/dictconfig.py", line 59, in __setattr__
      self.__setitem__(key, value)
    File "/private/home/bda/anaconda3/lib/python3.7/site-packages/omegaconf-1.3.0-py3.7.egg/omegaconf/dictconfig.py", line 28, in __setitem__
      raise KeyError("Accessing unknown key in a struct : {}".format(self.get_full_key(key)))
  KeyError: 'Accessing unknown key in a struct : hydra.job.num_jobs'
  ```
  
  ---
  
  Perhaps hydra needs to add the right placeholders in the config here for the plugins to modify/write into, or the plugin needs to have a temporarily config that's not locked?
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `plugins/submitit/hydra_plugins/submitit/submitit_launcher.py`
  Content:
  ```
  1 # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
  2 import logging
  3 import os
  4 
  5 import hydra._internal.utils
  6 import hydra.plugins.common.utils
  7 from hydra.plugins import Launcher
  8 
  9 from omegaconf import open_dict
  10 
  11 # pylint: disable=C0103
  12 log = logging.getLogger(__name__)
  13 
  14 
  15 class SubmititLauncher(Launcher):
  16     def __init__(self, queue, folder, queue_parameters, conda_file=None):
  17         self.queue = queue
  18         self.queue_parameters = queue_parameters
  19         self.folder = folder
  20         self.conda_file = conda_file
  21         self.config = None
  22         self.task_function = None
  23         self.verbose = None
  24         self.sweep_configs = None
  25         self.config_loader = None
  26 
  27     def setup(self, config, config_loader, task_function, verbose):
  28         self.config = config
  29         self.config_loader = config_loader
  30         self.task_function = task_function
  31         self.verbose = verbose
  32 
  33     def launch_job(self, sweep_overrides, job_dir_key, job_num):
  34         hydra.plugins.common.utils.configure_log(None, self.verbose)
  35         hydra.plugins.common.utils.setup_globals()
  36         sweep_config = self.config_loader.load_sweep_config(
  37             self.config, sweep_overrides
  38         )
  39         with open_dict(sweep_config):
  40             # Populate new job variables
  41             if "SLURM_JOB_ID" in os.environ:
  42                 sweep_config.hydra.job.id = os.environ["SLURM_JOB_ID"]
  43             elif "CHRONOS_JOB_ID" in os.environ:
  44                 sweep_config.hydra.job.id = os.environ["CHRONOS_JOB_ID"]
  45             else:
  46                 sweep_config.hydra.job.id = "unknown"
  47 
  48             sweep_config.hydra.job.num = job_num
  49             sweep_config.hydra.job.override_dirname = hydra.plugins.common.utils.get_overrides_dirname(
  50                 sweep_config.hydra.overrides.task
  51             )
  52 
  53         return hydra.plugins.common.utils.run_job(
  54             config=sweep_config,
  55             task_function=self.task_function,
  56             verbose=self.verbose,
  57             job_dir_key=job_dir_key,
  58             job_subdir_key="hydra.sweep.subdir",
  59         )
  60 
  61     def launch(self, job_overrides):
  62         import submitit
  63 
  64         num_jobs = len(job_overrides)
  65         assert num_jobs > 0
  66         self.config.hydra.job.num_jobs = num_jobs
  67         if self.queue == "auto":
  68             executor = submitit.AutoExecutor(
  69                 folder=self.folder, conda_file=self.conda_file
  70             )
  71         elif self.queue == "slurm":
  72             executor = submitit.SlurmExecutor(folder=self.folder)
  73         elif self.queue == "chronos":
  74             executor = submitit.ChronosExecutor(
  75                 folder=self.folder, conda_file=self.conda_file
  76             )
  77         elif self.queue == "local":
  78             executor = submitit.LocalExecutor(folder=self.folder)
  79         else:
  80             raise RuntimeError("Unsupported queue type {}".format(self.queue))
  81 
  82         executor.update_parameters(**self.queue_parameters[self.queue])
  83 
  84         log.info("Sweep output dir : {}".format(self.config.hydra.sweep.dir))
  85         path_str = str(self.config.hydra.sweep.dir)
  86         os.makedirs(path_str, exist_ok=True)
  87         if self.config.hydra.sweep.mode is not None:
  88             mode = int(str(self.config.hydra.sweep.mode), 8)
  89             os.chmod(path_str, mode=mode)
  90 
  91         jobs = []
  92         for job_num in range(num_jobs):
  93             sweep_override = list(job_overrides[job_num])
  94             log.info(
  95                 "\t#{} : {}".format(
  96                     job_num,
  97                     " ".join(
  98                         hydra.plugins.common.utils.filter_overrides(sweep_override)
  99                     ),
  100                 )
  101             )
  102             job = executor.submit(
  103                 self.launch_job, sweep_override, "hydra.sweep.dir", job_num
  104             )
  105             jobs.append(job)
  106 
  107         return [j.results() for j in jobs]
  108
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py b/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py
  --- a/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py
  +++ b/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py
  @@ -60,11 +60,14 @@
           )
   
       def launch(self, job_overrides):
  +        # lazy import to ensurue plugin discovery remains fast
           import submitit
   
           num_jobs = len(job_overrides)
           assert num_jobs > 0
  -        self.config.hydra.job.num_jobs = num_jobs
  +        with open_dict(self.config):
  +            self.config.hydra.job.num_jobs = num_jobs
  +
           if self.queue == "auto":
               executor = submitit.AutoExecutor(
                   folder=self.folder, conda_file=self.conda_file, par_file=self.par_file
  @@ -85,7 +88,7 @@
           log.info("Sweep output dir : {}".format(self.config.hydra.sweep.dir))
           path_str = str(self.config.hydra.sweep.dir)
           os.makedirs(path_str, exist_ok=True)
  -        if self.config.hydra.sweep.mode is not None:
  +        if "mode" in self.config.hydra.sweep:
               mode = int(str(self.config.hydra.sweep.mode), 8)
               os.chmod(path_str, mode=mode)
  
verification_info: {"golden_diff": "diff --git a/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py b/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py\n--- a/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py\n+++ b/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py\n@@ -60,11 +60,14 @@\n         )\n \n     def launch(self, job_overrides):\n+        # lazy import to ensurue plugin discovery remains fast\n         import submitit\n \n         num_jobs = len(job_overrides)\n         assert num_jobs > 0\n-        self.config.hydra.job.num_jobs = num_jobs\n+        with open_dict(self.config):\n+            self.config.hydra.job.num_jobs = num_jobs\n+\n         if self.queue == \"auto\":\n             executor = submitit.AutoExecutor(\n                 folder=self.folder, conda_file=self.conda_file, par_file=self.par_file\n@@ -85,7 +88,7 @@\n         log.info(\"Sweep output dir : {}\".format(self.config.hydra.sweep.dir))\n         path_str = str(self.config.hydra.sweep.dir)\n         os.makedirs(path_str, exist_ok=True)\n-        if self.config.hydra.sweep.mode is not None:\n+        if \"mode\" in self.config.hydra.sweep:\n             mode = int(str(self.config.hydra.sweep.mode), 8)\n             os.chmod(path_str, mode=mode)\n", "issue": "Error when using strict mode and multirun\nModifying the `6_sweep` example to have `@hydra.main(config_path=\"conf/config.yaml\", strict=True)` causes this error:\r\n\r\n```python3\r\n6_sweep(master*)$ python3 experiment.py -m\r\nTraceback (most recent call last):\r\n  File \"experiment.py\", line 15, in <module>\r\n    experiment()\r\n  File \"/private/home/bda/repos/hydra/hydra/main.py\", line 62, in decorated_main\r\n    run_hydra(get_args(), task_function, config_path, strict)\r\n  File \"/private/home/bda/repos/hydra/hydra/_internal/utils.py\", line 57, in run_hydra\r\n    hydra.multirun(overrides=args.overrides)\r\n  File \"/private/home/bda/repos/hydra/hydra/_internal/hydra.py\", line 124, in multirun\r\n    return sweeper.sweep(arguments=task_overrides)\r\n  File \"/private/home/bda/repos/hydra/hydra/plugins/step_sweeper.py\", line 63, in sweep\r\n    results = self.launcher.launch(batch)\r\n  File \"/private/home/bda/repos/hydra/plugins/submitit/hydra_plugins/submitit/submitit_launcher.py\", line 67, in launch\r\n    self.config.hydra.job.num_jobs = num_jobs\r\n  File \"/private/home/bda/anaconda3/lib/python3.7/site-packages/omegaconf-1.3.0-py3.7.egg/omegaconf/dictconfig.py\", line 59, in __setattr__\r\n    self.__setitem__(key, value)\r\n  File \"/private/home/bda/anaconda3/lib/python3.7/site-packages/omegaconf-1.3.0-py3.7.egg/omegaconf/dictconfig.py\", line 28, in __setitem__\r\n    raise KeyError(\"Accessing unknown key in a struct : {}\".format(self.get_full_key(key)))\r\nKeyError: 'Accessing unknown key in a struct : hydra.job.num_jobs'\r\n```\r\n\r\n---\r\n\r\nPerhaps hydra needs to add the right placeholders in the config here for the plugins to modify/write into, or the plugin needs to have a temporarily config that's not locked?\n", "before_files": [{"content": "# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\nimport logging\nimport os\n\nimport hydra._internal.utils\nimport hydra.plugins.common.utils\nfrom hydra.plugins import Launcher\n\nfrom omegaconf import open_dict\n\n# pylint: disable=C0103\nlog = logging.getLogger(__name__)\n\n\nclass SubmititLauncher(Launcher):\n    def __init__(self, queue, folder, queue_parameters, conda_file=None):\n        self.queue = queue\n        self.queue_parameters = queue_parameters\n        self.folder = folder\n        self.conda_file = conda_file\n        self.config = None\n        self.task_function = None\n        self.verbose = None\n        self.sweep_configs = None\n        self.config_loader = None\n\n    def setup(self, config, config_loader, task_function, verbose):\n        self.config = config\n        self.config_loader = config_loader\n        self.task_function = task_function\n        self.verbose = verbose\n\n    def launch_job(self, sweep_overrides, job_dir_key, job_num):\n        hydra.plugins.common.utils.configure_log(None, self.verbose)\n        hydra.plugins.common.utils.setup_globals()\n        sweep_config = self.config_loader.load_sweep_config(\n            self.config, sweep_overrides\n        )\n        with open_dict(sweep_config):\n            # Populate new job variables\n            if \"SLURM_JOB_ID\" in os.environ:\n                sweep_config.hydra.job.id = os.environ[\"SLURM_JOB_ID\"]\n            elif \"CHRONOS_JOB_ID\" in os.environ:\n                sweep_config.hydra.job.id = os.environ[\"CHRONOS_JOB_ID\"]\n            else:\n                sweep_config.hydra.job.id = \"unknown\"\n\n            sweep_config.hydra.job.num = job_num\n            sweep_config.hydra.job.override_dirname = hydra.plugins.common.utils.get_overrides_dirname(\n                sweep_config.hydra.overrides.task\n            )\n\n        return hydra.plugins.common.utils.run_job(\n            config=sweep_config,\n            task_function=self.task_function,\n            verbose=self.verbose,\n            job_dir_key=job_dir_key,\n            job_subdir_key=\"hydra.sweep.subdir\",\n        )\n\n    def launch(self, job_overrides):\n        import submitit\n\n        num_jobs = len(job_overrides)\n        assert num_jobs > 0\n        self.config.hydra.job.num_jobs = num_jobs\n        if self.queue == \"auto\":\n            executor = submitit.AutoExecutor(\n                folder=self.folder, conda_file=self.conda_file\n            )\n        elif self.queue == \"slurm\":\n            executor = submitit.SlurmExecutor(folder=self.folder)\n        elif self.queue == \"chronos\":\n            executor = submitit.ChronosExecutor(\n                folder=self.folder, conda_file=self.conda_file\n            )\n        elif self.queue == \"local\":\n            executor = submitit.LocalExecutor(folder=self.folder)\n        else:\n            raise RuntimeError(\"Unsupported queue type {}\".format(self.queue))\n\n        executor.update_parameters(**self.queue_parameters[self.queue])\n\n        log.info(\"Sweep output dir : {}\".format(self.config.hydra.sweep.dir))\n        path_str = str(self.config.hydra.sweep.dir)\n        os.makedirs(path_str, exist_ok=True)\n        if self.config.hydra.sweep.mode is not None:\n            mode = int(str(self.config.hydra.sweep.mode), 8)\n            os.chmod(path_str, mode=mode)\n\n        jobs = []\n        for job_num in range(num_jobs):\n            sweep_override = list(job_overrides[job_num])\n            log.info(\n                \"\\t#{} : {}\".format(\n                    job_num,\n                    \" \".join(\n                        hydra.plugins.common.utils.filter_overrides(sweep_override)\n                    ),\n                )\n            )\n            job = executor.submit(\n                self.launch_job, sweep_override, \"hydra.sweep.dir\", job_num\n            )\n            jobs.append(job)\n\n        return [j.results() for j in jobs]\n", "path": "plugins/submitit/hydra_plugins/submitit/submitit_launcher.py"}], "after_files": [{"content": "# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved\nimport logging\nimport os\n\nimport hydra._internal.utils\nimport hydra.plugins.common.utils\nfrom hydra.plugins import Launcher\n\nfrom omegaconf import open_dict\n\n# pylint: disable=C0103\nlog = logging.getLogger(__name__)\n\n\nclass SubmititLauncher(Launcher):\n    def __init__(self, queue, folder, queue_parameters, conda_file=None, par_file=None):\n        self.queue = queue\n        self.queue_parameters = queue_parameters\n        self.folder = folder\n        self.conda_file = conda_file\n        self.par_file = par_file\n        self.config = None\n        self.task_function = None\n        self.verbose = None\n        self.sweep_configs = None\n        self.config_loader = None\n\n    def setup(self, config, config_loader, task_function, verbose):\n        self.config = config\n        self.config_loader = config_loader\n        self.task_function = task_function\n        self.verbose = verbose\n\n    def launch_job(self, sweep_overrides, job_dir_key, job_num):\n        hydra.plugins.common.utils.configure_log(None, self.verbose)\n        hydra.plugins.common.utils.setup_globals()\n        sweep_config = self.config_loader.load_sweep_config(\n            self.config, sweep_overrides\n        )\n        with open_dict(sweep_config):\n            # Populate new job variables\n            if \"SLURM_JOB_ID\" in os.environ:\n                sweep_config.hydra.job.id = os.environ[\"SLURM_JOB_ID\"]\n            elif \"CHRONOS_JOB_ID\" in os.environ:\n                sweep_config.hydra.job.id = os.environ[\"CHRONOS_JOB_ID\"]\n            else:\n                sweep_config.hydra.job.id = \"unknown\"\n\n            sweep_config.hydra.job.num = job_num\n            sweep_config.hydra.job.override_dirname = hydra.plugins.common.utils.get_overrides_dirname(\n                sweep_config.hydra.overrides.task\n            )\n\n        return hydra.plugins.common.utils.run_job(\n            config=sweep_config,\n            task_function=self.task_function,\n            verbose=self.verbose,\n            job_dir_key=job_dir_key,\n            job_subdir_key=\"hydra.sweep.subdir\",\n        )\n\n    def launch(self, job_overrides):\n        # lazy import to ensurue plugin discovery remains fast\n        import submitit\n\n        num_jobs = len(job_overrides)\n        assert num_jobs > 0\n        with open_dict(self.config):\n            self.config.hydra.job.num_jobs = num_jobs\n\n        if self.queue == \"auto\":\n            executor = submitit.AutoExecutor(\n                folder=self.folder, conda_file=self.conda_file, par_file=self.par_file\n            )\n        elif self.queue == \"slurm\":\n            executor = submitit.SlurmExecutor(folder=self.folder)\n        elif self.queue == \"chronos\":\n            executor = submitit.ChronosExecutor(\n                folder=self.folder, conda_file=self.conda_file, par_file=self.par_file\n            )\n        elif self.queue == \"local\":\n            executor = submitit.LocalExecutor(folder=self.folder)\n        else:\n            raise RuntimeError(\"Unsupported queue type {}\".format(self.queue))\n\n        executor.update_parameters(**self.queue_parameters[self.queue])\n\n        log.info(\"Sweep output dir : {}\".format(self.config.hydra.sweep.dir))\n        path_str = str(self.config.hydra.sweep.dir)\n        os.makedirs(path_str, exist_ok=True)\n        if \"mode\" in self.config.hydra.sweep:\n            mode = int(str(self.config.hydra.sweep.mode), 8)\n            os.chmod(path_str, mode=mode)\n\n        jobs = []\n        for job_num in range(num_jobs):\n            sweep_override = list(job_overrides[job_num])\n            log.info(\n                \"\\t#{} : {}\".format(\n                    job_num,\n                    \" \".join(\n                        hydra.plugins.common.utils.filter_overrides(sweep_override)\n                    ),\n                )\n            )\n            job = executor.submit(\n                self.launch_job, sweep_override, \"hydra.sweep.dir\", job_num\n            )\n            jobs.append(job)\n\n        return [j.results() for j in jobs]\n", "path": "plugins/submitit/hydra_plugins/submitit/submitit_launcher.py"}]}