pypa/pip · error · ConfigurationError
Key does not contain dot separated section and key. Perhaps…
Error message
Key does not contain dot separated section and key. Perhaps you wanted to use 'global.{name}' instead? What it means
Raised by _disassemble_key() when a configuration key passed to pip config does not contain a dot separator. pip's configuration API requires keys in 'section.name' form (e.g. 'global.index-url'), because it maps to an INI section plus option. A bare key like 'index-url' is ambiguous and pip suggests prefixing it with a section such as 'global.'.
Solutions
- Prefix the key with the appropriate section: `global.`, `user.`, or `site.` — e.g. `pip config set global.index-url https://...`.
- Consult `pip config list` to see the correct section.key format for existing entries.
- If editing a specific file, use `pip config set --site global.index-url ...` (the section prefix is always required regardless of --user/--global/--site scope).
Example fix
# before pip config set index-url https://pypi.org/simple # after pip config set global.index-url https://pypi.org/simple
Defensive patterns
Strategy: validation
Validate before calling
import re
def validate_config_key(key: str) -> str:
if not re.match(r'^(global|user|site|install)\.[A-Za-z0-9_-]+$', key):
raise ValueError(f"Config key must be 'section.name', got: {key!r}")
return key
Type guard
def is_dotted_config_key(key: str) -> bool:
return '.' in key and key.split('.', 1)[0] in {'global', 'user', 'site', 'install'}
Prevention
- Always prefix config keys with a section (global./user./site.).
- Use `pip config list` to learn the correct key format.
When it happens
Trigger: Running `pip config set index-url https://...` (missing section prefix), or `pip config get timeout`, or `pip config unset index-url`. Any config subcommand that ultimately calls set_value/get_value/unset_value and hits _disassemble_key with a dotless string.
Common situations: Forgetting the section prefix when scripting `pip config set`; copying a pip.conf option name without its section; muscle memory from tools that take bare option names.
Related errors
- Needed a specific file to be modifying.
- Got invalid value for load_only - should be one of
- No such key
- An error occurred while writing to the configuration file
- Can not perform a '--user' install. User site-packages are…
AI-assisted analysis of pypa/pip@f399c37189 (2026-08-08).
Data as JSON: /api/errors/b02163d1282b3301.
Report an issue: GitHub.
Appendix: source
Thrown at src/pip/_internal/configuration.py:65
logger = getLogger(__name__)
# NOTE: Maybe use the optionx attribute to normalize keynames.
def _normalize_name(name: str) -> str:
"""Make a name consistent regardless of source (environment or file)"""
name = name.lower().replace("_", "-")
name = name.removeprefix("--") # only prefer long opts
return name
def _disassemble_key(name: str) -> list[str]:
if "." not in name:
error_message = (
"Key does not contain dot separated section and key. "
f"Perhaps you wanted to use 'global.{name}' instead?"
)
raise ConfigurationError(error_message)
return name.split(".", 1)
def get_configuration_files() -> dict[Kind, list[str]]:
global_config_files = [
os.path.join(path, CONFIG_BASENAME) for path in appdirs.site_config_dirs("pip")
]
site_config_file = os.path.join(sys.prefix, CONFIG_BASENAME)
legacy_config_file = os.path.join(
os.path.expanduser("~"),
"pip" if WINDOWS else ".pip",
CONFIG_BASENAME,
)
new_config_file = os.path.join(appdirs.user_config_dir("pip"), CONFIG_BASENAME)
return {
kinds.GLOBAL: global_config_files,
kinds.SITE: [site_config_file],View on GitHub (pinned to f399c37189)