pypa/pip · error · ConfigurationError
An error occurred while writing to the configuration file
Error message
An error occurred while writing to the configuration file {fname}: {error} What it means
Raised by Configuration.save() when opening or writing the target config file raises an OSError. This wraps the underlying OS error (permission denied, disk full, path too long, read-only filesystem) with the filename so the user knows which file failed.
Solutions
- Check the file path shown in the message and verify write permissions (`ls -l` on the file and its directory).
- Run with appropriate privileges or fix ownership: `sudo chown $USER <dir>` or write to --user scope which targets your home directory.
- Free disk space if full; remount read-write filesystems.
- Ensure the parent directory exists (pip tries ensure_dir, but permissions may block creation).
Example fix
# before (global file owned by root) pip config set global.index-url https://... # -> OSError # after pip config set --user user.index-url https://...
Defensive patterns
Strategy: validation
Validate before calling
import os
def ensure_config_writable(path: str) -> None:
d = os.path.dirname(path) or '.'
if not os.path.isdir(d):
os.makedirs(d, exist_ok=True)
if os.path.exists(path) and not os.access(path, os.W_OK):
raise PermissionError(f'{path} is not writable')
if not os.access(d, os.W_OK):
raise PermissionError(f'{d} is not writable')
Try / catch
from pip._internal.exceptions import ConfigurationError
try:
cfg.save()
except ConfigurationError as e:
# fall back to user scope if global is not writable
print(f'Could not write config: {e}; try --user scope')
Prevention
- Check directory/file write permissions before `pip config set`.
- Prefer --user scope to avoid permission issues on system config files.
- Ensure adequate disk space.
When it happens
Trigger: Running `pip config set ...` where the target file path is not writable (permission denied), the disk is full, the parent directory does not exist and cannot be created, or the filesystem is read-only (e.g. a mounted squashfs or container layer).
Common situations: System-managed pip.conf owned by root while running as non-root; full disk; container with a read-only layer; SELinux/AppArmor denying writes; path pointing to a directory rather than a file.
Related errors
- Configuration file contains invalid
- Configuration file could not be loaded.\n
- Error reading
- Failed to build one or more wheels
- Fatal Internal error [id=1]. Please report as a bug.
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/d54d727ea2cdb621.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/configuration.py:228
except KeyError:
del self._config[self.load_only][key]
def save(self) -> None:
"""Save the current in-memory state."""
self._ensure_have_load_only()
for fname, parser in self._modified_parsers:
logger.info("Writing to %s", fname)
# Ensure directory exists.
ensure_dir(os.path.dirname(fname))
# Ensure directory's permission(need to be writeable)
try:
with open(fname, "w") as f:
parser.write(f)
except OSError as error:
raise ConfigurationError(
f"An error occurred while writing to the configuration file "
f"{fname}: {error}"
)
#
# Private routines
#
def _ensure_have_load_only(self) -> None:
if self.load_only is None:
raise ConfigurationError("Needed a specific file to be modifying.")
logger.debug("Will be working with %s variant only", self.load_only)
@property
def _dictionary(self) -> dict[str, dict[str, Any]]:
"""A dictionary representing the loaded configuration."""
# NOTE: Dictionaries are not populated if not loaded. So, conditionals
# are not needed here.View on GitHub (pinned to f399c37189)