{"record":{"id":"1acfd73e8c9b5f76","repo":"affaan-m/ECC","slug":"config-file-not-found-path","errorCode":null,"errorMessage":"Config file not found: {path}","messagePattern":"Config file not found: (.+?)","errorType":"exception","errorClass":"ConfigError","httpStatus":null,"severity":"error","filePath":"skills/python-patterns/SKILL.md","lineNumber":151,"sourceCode":"        \"\"\"Render the object to a string.\"\"\"\n\ndef render_all(items: list[Renderable]) -> str:\n    \"\"\"Render all items that implement the Renderable protocol.\"\"\"\n    return \"\\n\".join(item.render() for item in items)\n```\n\n## Error Handling Patterns\n\n### Specific Exception Handling\n\n```python\n# Good: Catch specific exceptions\ndef load_config(path: str) -> Config:\n    try:\n        with open(path) as f:\n            return Config.from_json(f.read())\n    except FileNotFoundError as e:\n        raise ConfigError(f\"Config file not found: {path}\") from e\n    except json.JSONDecodeError as e:\n        raise ConfigError(f\"Invalid JSON in config: {path}\") from e\n\n# Bad: Bare except\ndef load_config(path: str) -> Config:\n    try:\n        with open(path) as f:\n            return Config.from_json(f.read())\n    except:\n        return None  # Silent failure!\n```\n\n### Exception Chaining\n\n```python\ndef process_data(data: str) -> Result:\n    try:\n        parsed = json.loads(data)","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/skills/python-patterns/SKILL.md#L133-L169","documentation":"`load_config` catches `FileNotFoundError` from `open(path)` and re-raises it as a domain `ConfigError(f\"Config file not found: {path}\")` using exception chaining (`from e`). This is the 'specific exception handling' pattern — the alternative `except:` bare clause that returns `None` is shown as the anti-pattern.","triggerScenarios":"Caller passes a path that does not exist on disk: wrong working directory, typo, missing config in deployment, env var pointing at `/etc/app/config.json` that was not mounted.","commonSituations":"Working directory differs between dev and container so the relative path resolves wrong. Helm/k8s forgot to mount the ConfigMap. CI runs from repo root but the app expects `./config/`. Path built from an env var that was unset, yielding `None` or `''`.","solutions":["Verify the path with `pathlib.Path(path).resolve()` and `is_file()` before calling, and log the resolved absolute path.","Confirm the working directory the process runs from (containers often start in `/app`, not the repo root).","For deployments, ensure the config file is mounted/copied into the image at the expected absolute path.","Make the path required and absolute in production; fall back to a packaged default only for dev."],"exampleFix":"# before\ntry:\n    with open(path) as f:\n        return Config.from_json(f.read())\nexcept FileNotFoundError as e:\n    raise ConfigError(f\"Config file not found: {path}\") from e\n\n# after — resolve+validate before open, clearer message\nfrom pathlib import Path\np = Path(path).expanduser().resolve()\nif not p.is_file():\n    raise ConfigError(f\"Config file not found: {p} (cwd={Path.cwd()})\")\nwith p.open() as f:\n    return Config.from_json(f.read())","handlingStrategy":"validation","validationCode":"from pathlib import Path\ndef config_exists(path: str) -> bool:\n    return Path(path).expanduser().is_file()","typeGuard":"null","tryCatchPattern":"try:\n    cfg = load_config(path)\nexcept ConfigError as e:\n    if 'not found' in str(e):\n        fall_back_to_packaged_default()\n    raise","preventionTips":["Resolve and validate the path with `pathlib` before `open`.","Use absolute paths in production; ship a packaged default for dev.","Log the resolved absolute path and current working directory in the error."],"tags":["python","configuration","error-handling","io","patterns"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}