affaan-m/ECC · error · ConfigError
Invalid JSON in config: {path}
Error message
Invalid JSON in config: {path} What it means
Raised as a ConfigError when Python's json.JSONDecodeError is caught while parsing a config file with Config.from_json(f.read()). It signals the file was opened successfully but its contents are not valid JSON. The exception is chained (`from e`) so the original decode error traceback is preserved.
Source
Thrown at skills/python-patterns/SKILL.md:153
def render_all(items: list[Renderable]) -> str:
"""Render all items that implement the Renderable protocol."""
return "\n".join(item.render() for item in items)
```
## Error Handling Patterns
### Specific Exception Handling
```python
# Good: Catch specific exceptions
def load_config(path: str) -> Config:
try:
with open(path) as f:
return Config.from_json(f.read())
except FileNotFoundError as e:
raise ConfigError(f"Config file not found: {path}") from e
except json.JSONDecodeError as e:
raise ConfigError(f"Invalid JSON in config: {path}") from e
# Bad: Bare except
def load_config(path: str) -> Config:
try:
with open(path) as f:
return Config.from_json(f.read())
except:
return None # Silent failure!
```
### Exception Chaining
```python
def process_data(data: str) -> Result:
try:
parsed = json.loads(data)
except json.JSONDecodeError as e:
# Chain exceptions to preserve the tracebackView on GitHub (pinned to 01e15490f0)
Solutions
- Validate the file with `python -m json.tool config.json` to get the exact line/column of the syntax error.
- Check for common JSON-invalid syntax: comments (// or /* */), trailing commas, single-quoted strings, unquoted keys.
- Re-encode the file as plain UTF-8 without BOM (e.g. `sed -i '1s/^\xEF\xBB\xBF//' config.json`).
- If you must allow comments/relaxed JSON, parse with json5.loads or strip comments before json.loads, but document that the config schema is no longer strict JSON.
Example fix
// before
{}
# after: validate and report the exact offset
import json
try:
with open(path) as f:
return Config.from_json(f.read())
except json.JSONDecodeError as e:
raise ConfigError(f"Invalid JSON in {path} at line {e.lineno} col {e.colno}: {e.msg}") from e Defensive patterns
Strategy: validation
Validate before calling
import json, pathlib
def is_valid_json_file(path):
p = pathlib.Path(path)
if not p.exists():
return False, "file missing"
try:
json.loads(p.read_text(encoding="utf-8"))
return True, None
except json.JSONDecodeError as e:
return False, f"line {e.lineno} col {e.colno}: {e.msg}"
ok, err = is_valid_json_file(path)
if not ok:
raise SystemExit(f"refusing to load bad config: {err}") Type guard
def is_json_decodable(s: str) -> bool:
try:
json.loads(s)
return True
except (json.JSONDecodeError, TypeError):
return False Try / catch
try:
cfg = load_config(path)
except ConfigError as e:
log.error("config load failed: %s", e)
raise SystemExit(2)
except FileNotFoundError as e:
log.error("config file missing: %s", e)
raise SystemExit(2) Prevention
- Lint config files in CI with `python -m json.tool`.
- Generate configs from code/templates rather than hand-editing JSON.
- Keep configs as TOML/YAML with a schema if comments are needed, and validate at startup.
When it happens
Trigger: Calling load_config(path) where the file at `path` exists but contains malformed JSON (trailing commas, single quotes, unquoted keys, BOM-prefixed bytes, comments, or a file truncated mid-write). Config.from_json() internally calls json.loads() which raises json.JSONDecodeError.
Common situations: Hand-edited JSON config files with comments or trailing commas; a config written by another tool that emitted JSON5 or JSONC; a config file partially written and read during a crash; UTF-8 with BOM from a Windows editor.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- MCP config must be a JSON object
- MCP config must include an mcpServers object
- Failed to parse data: {data}
- ECC_PROJECT_DIR must be a child path within /workspace.
- Unknown argument: ${arg}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/95fee8ce8247bee5.
Report an issue: GitHub.