{"record":{"id":"2f1875ac1d01ce43","repo":"deepfakes/faceswap","slug":"config-file-does-not-exist-at-ini-path","errorCode":null,"errorMessage":"Config file does not exist at: {ini_path}","messagePattern":"Config file does not exist at: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/config/ini.py","lineNumber":60,"sourceCode":"        return os.path.isfile(self._file_path)\n\n    def _get_config_path(self, ini_path: str | None) -> str:\n        \"\"\"Return the path to the config file from the calling folder or the provided file\n\n        Parameters\n        ----------\n        ini_path\n            Path to a config ini file. ``None`` for default location.\n\n        Returns\n        -------\n        The full path to the configuration file\n        \"\"\"\n        if ini_path is not None:\n            if not os.path.isfile(ini_path):\n                err = f\"Config file does not exist at: {ini_path}\"\n                logger.error(err)\n                raise ValueError(err)\n            return ini_path\n\n        retval = os.path.join(PROJECT_ROOT, \"config\", f\"{self._plugin_group}.ini\")\n        logger.debug(\"[%s] Config File location: '%s'\", os.path.basename(retval), retval)\n        return retval\n\n    def _get_new_configparser(self) -> ConfigParser:\n        \"\"\"Obtain a fresh ConfigParser object and set it to case-sensitive\n\n        Returns\n        -------\n        A new ConfigParser object set to case-sensitive\n        \"\"\"\n        retval = ConfigParser(allow_no_value=True)\n        retval.optionxform = str  # type:ignore[assignment,method-assign]\n        return retval\n\n    # I/O","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/deepfakes/faceswap/blob/f530cb7508ae670f6474f8a7d9c4df94705cf96b/lib/config/ini.py#L42-L78","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a list literal (['v1','v2']) or a comma-separated string ('v1,v2')","If the value may be any iterable, normalize first: list(value) if not isinstance(value, str) else value","Check the option's datatype in lib/config/objects.py and the plugin's default to confirm list is expected"],"exampleFix":"# before\noption.set((\"components\", \"extended\"))  # tuple -> ValueError\n\n# after\noption.set([\"components\", \"extended\"])   # list\n# or\noption.set(\"components,extended\")        # str, parsed to list","handlingStrategy":"type-guard","validationCode":"import os\n\ndef config_path_ok(path):\n    return os.path.isfile(path)\n\npath = \"config/custom.ini\"\nif not config_path_ok(path):\n    raise SystemExit(f\"config file missing: {path}\")","typeGuard":"def is_valid_ini(path: str) -> bool:\n    \"\"\"True when path exists and is a regular file usable by the ini loader.\"\"\"\n    import os\n    return isinstance(path, str) and os.path.isfile(path)","tryCatchPattern":"try:\n    cfg = FaceswapConfig(ini_path=path)\nexcept ValueError as err:\n    if \"does not exist\" in str(err):\n        cfg = FaceswapConfig()  # fall back to default location\n    else:\n        raise","preventionTips":["Validate explicit config paths with os.path.isfile before passing","Keep configs in version control so paths always resolve","Pass None to use the managed default location instead of guessing"],"tags":["faceswap","config","validation","list","type-error"],"backgroundTag":null,"analyzedSha":"f530cb7508ae670f6474f8a7d9c4df94705cf96b","analyzedAt":"2026-08-15T02:59:26.626Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}