{"record":{"id":"8eb1bc3f7adbd871","repo":"HKUDS/Vibe-Trading","slug":"invalid-futu-config-at-path-exc","errorCode":null,"errorMessage":"invalid Futu config at {path}: {exc}","messagePattern":"invalid Futu config at (.+?): (.+?)","errorType":"exception","errorClass":"FutuConfigError","httpStatus":null,"severity":"error","filePath":"agent/src/trading/connectors/futu/sdk.py","lineNumber":198,"sourceCode":"    cfg = FutuConfig.from_mapping(base)\n    clean = {k: v for k, v in dict(overrides or {}).items() if k in _OVERRIDE_KEYS and v not in (None, \"\")}\n    return cfg.with_overrides(**clean) if clean else cfg\n\n\ndef config_path() -> Path:\n    \"\"\"Return the user-level Futu config path.\"\"\"\n    return get_runtime_root() / CONFIG_FILENAME\n\n\ndef load_config() -> FutuConfig:\n    \"\"\"Load Futu settings from ``~/.vibe-trading/futu.json``.\"\"\"\n    path = config_path()\n    if not path.exists():\n        return FutuConfig()\n    try:\n        return FutuConfig.from_mapping(json.loads(path.read_text(encoding=\"utf-8\")))\n    except (OSError, ValueError, json.JSONDecodeError) as exc:\n        raise FutuConfigError(f\"invalid Futu config at {path}: {exc}\") from exc\n\n\ndef save_config(config: FutuConfig) -> Path:\n    \"\"\"Persist Futu settings with owner-only permissions.\"\"\"\n    path = config_path()\n    path.parent.mkdir(parents=True, exist_ok=True)\n    path.write_text(json.dumps(asdict(config), indent=2, ensure_ascii=False) + \"\\n\", encoding=\"utf-8\")\n    try:\n        path.chmod(0o600)\n    except OSError:\n        pass\n    return path\n\n\ndef futu_available() -> bool:\n    \"\"\"Return whether the optional ``futu-api`` SDK can be imported.\"\"\"\n    try:\n        _require_futu()","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/trading/connectors/futu/sdk.py#L180-L216","documentation":"Raised by load_config when the Futu config file exists but cannot be read or parsed: OSError on read, or invalid JSON (ValueError/JSONDecodeError), or a value that fails type conversion in from_mapping.","triggerScenarios":"Malformed JSON in the futu config file (trailing comma, single quotes), unreadable file permissions, or non-numeric 'port' value.","commonSituations":"Hand-edited config with JSON syntax errors, file corrupted, port accidentally quoted as string in a way int() rejects, partial write/ interruption.","solutions":["Run the file through a JSON validator / json.tool to find the syntax error","Fix or regenerate the config file","Ensure 'port' is a number and fields match the expected schema"],"exampleFix":"// before\n{ \"profile\": \"paper\", \"port\": \"11111\", }  // trailing comma\n// after\n{ \"profile\": \"paper\", \"port\": 11111 }","handlingStrategy":"try-catch","validationCode":"import json, pathlib\np = config_path()\nif p.exists():\n    json.loads(p.read_text())  # dry-run parse before the SDK does","typeGuard":null,"tryCatchPattern":"try:\n    cfg = load_config()\nexcept FutuConfigError as exc:\n    logger.error('bad futu config: %s', exc)\n    cfg = FutuConfig()  # fall back to defaults or prompt re-setup","preventionTips":["Validate config JSON in CI or at app startup","Write configs programmatically (save_config) rather than by hand","Keep a schema check for port/host types"],"tags":["futu","config","json","file-io"],"backgroundTag":"invalid-config-file","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}