pypa/pip · error · ConfigurationFileCouldNotBeLoaded
Configuration file could not be loaded.\n{error}\n
Error message
Configuration file could not be loaded.\n{error}\n What it means
Raised by Configuration._construct_parser() when configparser raises a generic Error while reading the config file. This covers INI syntax problems: duplicate sections, duplicate options within a section, malformed lines, missing section headers, or bad interpolation. The underlying configparser error detail is appended.
Source
Thrown at src/pip/_internal/configuration.py:306
def _construct_parser(self, fname: str) -> RawConfigParser:
parser = configparser.RawConfigParser()
# If there is no such file, don't bother reading it but create the
# parser anyway, to hold the data.
# Doing this is useful when modifying and saving files, where we don't
# need to construct a parser.
if os.path.exists(fname):
locale_encoding = get_locale_encoding()
try:
parser.read(fname, encoding=locale_encoding)
except UnicodeDecodeError:
# See https://github.com/pypa/pip/issues/4963
raise ConfigurationFileCouldNotBeLoaded(
reason=f"contains invalid {locale_encoding} characters",
fname=fname,
)
except configparser.Error as error:
# See https://github.com/pypa/pip/issues/4893
raise ConfigurationFileCouldNotBeLoaded(error=error)
return parser
def _load_environment_vars(self) -> None:
"""Loads configuration from environment variables"""
self._config[kinds.ENV_VAR].setdefault(":env:", {})
self._config[kinds.ENV_VAR][":env:"].update(
self._normalized_keys(":env:", self.get_environ_vars())
)
def _normalized_keys(
self, section: str, items: Iterable[tuple[str, Any]]
) -> dict[str, Any]:
"""Normalizes items to construct a dictionary with normalized keys.
This routine is where the names become keys and are made the same
regardless of source - configuration files or environment.
"""
normalized = {}View on GitHub (pinned to f399c37189)
Solutions
- Open the file named in the error and fix the syntax: ensure all options are under a [section] header and there are no duplicate sections/options.
- Escape literal percent signs by doubling them (`%%`) to avoid configparser interpolation errors.
- Use `pip config set` / `pip config edit` instead of manual editing to avoid syntax mistakes.
- Run `pip config debug` to see all config files pip reads, then validate each one.
Example fix
# before (no section header) index-url = https://pypi.org/simple # after [global] index-url = https://pypi.org/simple
Defensive patterns
Strategy: validation
Validate before calling
import configparser
def validate_config_syntax(path: str) -> None:
p = configparser.RawConfigParser()
try:
p.read(path)
except configparser.Error as e:
raise ValueError(f'{path} has invalid INI syntax: {e}') from e
if not p.sections():
raise ValueError(f'{path} has no [section] header')
Prevention
- Use `pip config set`/`pip config edit` instead of hand-editing INI files.
- Ensure every option sits under a [section] header.
- Double any literal % characters to avoid interpolation errors.
When it happens
Trigger: A pip.conf missing the required [section] header; duplicate [global] sections; a line like `key = value` outside any section; a value containing unescaped `%` triggering interpolation errors; tabs vs spaces or stray characters.
Common situations: Hand-editing pip.conf and forgetting the section header; merging config snippets that create duplicate sections; copy-pasting a value with `%` signs (configparser tries interpolation); corrupt or truncated config files.
Related errors
- Key does not contain dot separated section and key. Perhaps
- Got invalid value for load_only - should be one of {}
- No such key - {orig_key}
- Fatal Internal error [id=1]. Please report as a bug.
- An error occurred while writing to the configuration file {f
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/84fba5c095c3ce75.
Report an issue: GitHub.