{"id":"3b371a8edb648188","repo":"python-poetry/poetry","slug":"key-join-keys-not-in-config-3b371a","errorCode":null,"errorMessage":"Key {'.'.join(keys)} not in config","messagePattern":"Key (.+?) not in config","errorType":"validation","errorClass":"PropertyNotFoundError","httpStatus":null,"severity":"error","filePath":"src/poetry/config/file_config_source.py","lineNumber":43,"sourceCode":"    def __init__(self, file: TOMLFile) -> None:\n        self._file = file\n\n    @property\n    def name(self) -> str:\n        return str(self._file.path)\n\n    @property\n    def file(self) -> TOMLFile:\n        return self._file\n\n    def get_property(self, key: str | Sequence[str]) -> Any:\n        keys = split_key(key)\n\n        config = self.file.read() if self.file.exists() else {}\n\n        for i, sub_key in enumerate(keys):\n            if sub_key not in config:\n                raise PropertyNotFoundError(f\"Key {'.'.join(keys)} not in config\")\n\n            if i == len(keys) - 1:\n                return config[sub_key]\n\n            config = config[sub_key]\n\n    def add_property(self, key: str | Sequence[str], value: Any) -> None:\n        with self.secure() as config:\n            keys = split_key(key)\n\n            for i, sub_key in enumerate(keys):\n                if sub_key not in config and i < len(keys) - 1:\n                    config[sub_key] = table()\n\n                if i == len(keys) - 1:\n                    config[sub_key] = value\n                    break\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/python-poetry/poetry/blob/92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54/src/poetry/config/file_config_source.py#L25-L61","documentation":"Same PropertyNotFoundError raised by FileConfigSource.get_property(), the TOML-file-backed config source. It reads the file (or defaults to {}) then walks the key segments; if any segment is missing it raises this error. Unlike DictConfigSource the data comes from a TOML file on disk, so the root cause is typically a missing or incomplete config file rather than an in-memory state issue.","triggerScenarios":"Calling FileConfigSource.get_property(key) when the TOML file either does not exist (defaults to empty dict) or does not contain the requested key path. For instance reading ['repositories','myrepo'] from a poetry.toml that has no [repositories] table.","commonSituations":"Fresh project with no poetry.toml yet, a corrupted or partially-written config file, a key that was removed via remove_property (which prunes empty parent tables), or querying a key that only exists in the global config but not the local file.","solutions":["Check that the TOML file exists at the expected path (FileConfigSource.file.path) and inspect its contents.","Catch PropertyNotFoundError and fall back to the global/merged config value via Config.get() which returns None for missing keys.","Use add_property to set the key before reading it if it should always be present."],"exampleFix":"# before\nvalue = source.get_property([\"repositories\", \"myrepo\"])\n# after\nfrom poetry.config.config_source import PropertyNotFoundError\ntry:\n    value = source.get_property([\"repositories\", \"myrepo\"])\nexcept PropertyNotFoundError:\n    value = config.get([\"repositories\", \"myrepo\"])  # falls through to merged config","handlingStrategy":"try-catch","validationCode":"from poetry.config.config_source import PropertyNotFoundError\n\ndef safe_get_file(source, key, default=None):\n    try:\n        return source.get_property(key)\n    except PropertyNotFoundError:\n        return default","typeGuard":"def file_key_exists(source, key) -> bool:\n    from poetry.config.config_source import PropertyNotFoundError\n    try:\n        source.get_property(key)\n        return True\n    except PropertyNotFoundError:\n        return False","tryCatchPattern":"from poetry.config.config_source import PropertyNotFoundError\n\ntry:\n    value = file_source.get_property([\"repositories\", \"myrepo\"])\nexcept PropertyNotFoundError:\n    # Key not present in the TOML config file (or file is missing)\n    value = None","preventionTips":["Check source.file.exists() before reading from a FileConfigSource.","Use Config.get() for reads that merge global and local sources and return None on missing keys.","When writing config migrations, always catch PropertyNotFoundError when probing for old keys."],"tags":["config","file-config-source","toml","property-not-found","valueerror"],"analyzedSha":"92b74dcfe348d0e01e14d40d6c1fa47a4ee04a54","analyzedAt":"2026-08-04T20:33:34.072Z","schemaVersion":2}