HKUDS/Vibe-Trading · critical · ValueError
invalid portfolio settings: {exc}
Error message
invalid portfolio settings: {exc} What it means
PortfolioSettingsStore.load wraps any OSError or JSONDecodeError raised while reading the settings file into a single ValueError with the underlying cause chained. It means the file exists but cannot be read or parsed, distinct from the downstream parse_settings schema errors.
Source
Thrown at agent/src/portfolio/config.py:246
self.path.with_name("connections.json") if path is not None else None
)
self.connection_store = connection_store or ConnectionStore(connection_path)
def load(self) -> PortfolioSettings:
"""Read persisted settings, creating an empty file on first use.
Returns:
The validated settings currently on disk.
Raises:
ValueError: If the file is unreadable, is not a JSON object, or
fails validation.
"""
if self.path.exists():
try:
payload = json.loads(self.path.read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
raise ValueError(f"invalid portfolio settings: {exc}") from exc
if not isinstance(payload, dict):
raise ValueError("invalid portfolio settings: root must be an object")
settings = parse_settings(payload, self.connection_store)
if any("profile_id" in source for source in payload.get("sources", [])):
self.save(settings)
return settings
settings = PortfolioSettings()
self.save(settings)
return settings
def save(self, settings: PortfolioSettings | dict[str, Any]) -> PortfolioSettings:
"""Validate and atomically persist settings with owner-only permissions.
Args:
settings: Settings object or raw dict to validate and store.
Returns:View on GitHub (pinned to 80ffdda44c)
Solutions
- Read the chained cause (__cause__) to see whether it is OSError (fix permissions/disk) or JSONDecodeError (fix syntax)
- Repair the JSON with json.tool or restore from backup
- Ensure only the library writes the file and the process has consistent permissions
Example fix
try:
settings = store.load()
except ValueError as exc:
cause = exc.__cause__ # OSError vs json.JSONDecodeError
log.error("portfolio settings unreadable: %s (%s)", exc, cause) Defensive patterns
Strategy: try-catch
Validate before calling
import json
try:
json.loads(store.path.read_text(encoding='utf-8'))
except (OSError, json.JSONDecodeError) as exc:
alert(f'portfolio settings unreadable: {exc}') Type guard
def settings_loadable(path) -> bool:
try:
return isinstance(json.loads(path.read_text(encoding='utf-8')), dict)
except (OSError, json.JSONDecodeError):
return False Try / catch
try:
settings = store.load()
except ValueError as exc:
cause = exc.__cause__
if isinstance(cause, OSError):
fix_permissions(store.path); settings = store.load()
elif isinstance(cause, json.JSONDecodeError):
settings = restore_settings_backup(store) Prevention
- Back up the settings file before manual edits
- Keep file ownership/permissions stable across deployments
- Inspect __cause__ to distinguish IO vs syntax problems
When it happens
Trigger: An unreadable file (permissions, I/O error) or malformed JSON at the configured settings path; any consumer (settings, sources, refresh, latest, reconnect_target, _fetch_fx) then propagates this error.
Common situations: Partial writes from a crashed process, permissions changed after a user switch, or manual edits introducing syntax errors in the settings file.
Related errors
- sources must be a list
- each portfolio source must be an object
- invalid portfolio settings: root must be an object
- Feishu QR login requires a JSON agent config; use ~/.vibe-tr
- agent config 'channels' must be an object
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/c7e75f3a8f4ac14e.
Report an issue: GitHub.