deepfakes/faceswap · error · ValueError

Config file does not exist at: {ini_path}

Error message

Config file does not exist at: {ini_path}

What it means

lib/config/objects.py ConfigOption.validate: when a config option's datatype is list, the value passed to set() must be a str (parsed on commas/whitespace) or an already-materialized list. Any other type raises ValueError naming the option and the offending type/value.

Source

Thrown at lib/config/ini.py:60

        return os.path.isfile(self._file_path)

    def _get_config_path(self, ini_path: str | None) -> str:
        """Return the path to the config file from the calling folder or the provided file

        Parameters
        ----------
        ini_path
            Path to a config ini file. ``None`` for default location.

        Returns
        -------
        The full path to the configuration file
        """
        if ini_path is not None:
            if not os.path.isfile(ini_path):
                err = f"Config file does not exist at: {ini_path}"
                logger.error(err)
                raise ValueError(err)
            return ini_path

        retval = os.path.join(PROJECT_ROOT, "config", f"{self._plugin_group}.ini")
        logger.debug("[%s] Config File location: '%s'", os.path.basename(retval), retval)
        return retval

    def _get_new_configparser(self) -> ConfigParser:
        """Obtain a fresh ConfigParser object and set it to case-sensitive

        Returns
        -------
        A new ConfigParser object set to case-sensitive
        """
        retval = ConfigParser(allow_no_value=True)
        retval.optionxform = str  # type:ignore[assignment,method-assign]
        return retval

    # I/O

View on GitHub (pinned to f530cb7508)

Solutions

  1. Pass a list literal (['v1','v2']) or a comma-separated string ('v1,v2')
  2. If the value may be any iterable, normalize first: list(value) if not isinstance(value, str) else value
  3. Check the option's datatype in lib/config/objects.py and the plugin's default to confirm list is expected

Example fix

# before
option.set(("components", "extended"))  # tuple -> ValueError

# after
option.set(["components", "extended"])   # list
# or
option.set("components,extended")        # str, parsed to list
Defensive patterns

Strategy: type-guard

Validate before calling

import os

def config_path_ok(path):
    return os.path.isfile(path)

path = "config/custom.ini"
if not config_path_ok(path):
    raise SystemExit(f"config file missing: {path}")

Type guard

def is_valid_ini(path: str) -> bool:
    """True when path exists and is a regular file usable by the ini loader."""
    import os
    return isinstance(path, str) and os.path.isfile(path)

Try / catch

try:
    cfg = FaceswapConfig(ini_path=path)
except ValueError as err:
    if "does not exist" in str(err):
        cfg = FaceswapConfig()  # fall back to default location
    else:
        raise

Prevention

When it happens

Trigger: Calling cli_option.set()/ConfigOption.set_default with datatype == list and a value that is an int, tuple, set, None or numpy array; e.g. setting a multi-select option to ('mask_1','mask_2') (tuple) instead of a list.

Common situations: Plugins or scripts programmatically writing settings; converting a config value between tuple and list when refactoring; loading config values from JSON/YAML that yield tuples or None.

Related errors


AI-assisted analysis of deepfakes/faceswap@f530cb7508 (2026-08-15). Data as JSON: /api/errors/2f1875ac1d01ce43. Report an issue: GitHub.