code: def check_config(config, path):
      
      messages = []
  
      config_copy = get_frozen_copy(config)
      missing_keys = set(DEFAULT_CONFIG.keys()) - set(config_copy.keys())
      if missing_keys:
          messages.append("Missing config keys {}!".format(missing_keys))
  
      for key, value in config_copy.items():
          if key not in DEFAULT_CONFIG:
              messages.append("Unknown key {} in {}!".format(key, path))
              continue
          if value is None:
              messages.append(_VALUE_UNDEFINED_MESSAGE.format(path=path, key=key))
          else:
              value_type = type(value)
              if isinstance(DEFAULT_CONFIG[key], Mapping) and 'by-cot-product' in DEFAULT_CONFIG[key]:
                  default_type = type(DEFAULT_CONFIG[key]['by-cot-product'][config['cot_product']])
              else:
                  default_type = type(DEFAULT_CONFIG[key])
              if value_type is not default_type:
                  messages.append(
                      "{} {}: type {} is not {}!".format(path, key, value_type, default_type)
                  )
          if value in ("...", b"..."):
              messages.append(_VALUE_UNDEFINED_MESSAGE.format(path=path, key=key))
          if key in ("provisioner_id", "worker_group", "worker_type", "worker_id") and not _is_id_valid(value):
              messages.append('{} doesn\'t match "{}" (required by Taskcluster)'.format(key, _GENERIC_ID_REGEX.pattern))
      return messages
docs: Validate the config against DEFAULT_CONFIG.
  
      Any unknown keys or wrong types will add error messages.
  
      Args:
          config (dict): the running config.
          path (str): the path to the config file, used in error messages.
  
      Returns:
          list: the error messages found when validating the config.