HKUDS/Vibe-Trading · error · ValueError
invalid portfolio connection id: {connection_id or '?'}
Error message
invalid portfolio connection id: {connection_id or '?'} What it means
A source's connection id (from 'connection_id' or legacy 'id', stripped and lowercased) must fully match _SOURCE_ID_RE; otherwise parsing aborts with the offending id (or '?' if empty). The regex enforces a safe slug charset for ids.
Source
Thrown at agent/src/portfolio/config.py:165
if currency not in {"USD", "CNY"}:
raise ValueError("display_currency must be USD or CNY")
raw_sources = payload.get("sources")
if not isinstance(raw_sources, list):
raise ValueError("sources must be a list")
if len(raw_sources) > 50:
raise ValueError("at most 50 portfolio sources are allowed")
seen_ids: set[str] = set()
sources: list[PortfolioSource] = []
for index, raw in enumerate(raw_sources):
if not isinstance(raw, dict):
raise ValueError("each portfolio source must be an object")
connection_id = (
str(raw.get("connection_id") or raw.get("id") or "").strip().lower()
)
if not _SOURCE_ID_RE.fullmatch(connection_id):
raise ValueError(f"invalid portfolio connection id: {connection_id or '?'}")
legacy_profile_id = str(raw.get("profile_id") or "").strip().lower()
if legacy_profile_id:
legacy_profile = profile_by_id(legacy_profile_id)
connection = store.ensure(
connection_id,
legacy_profile.id,
str(raw.get("label") or legacy_profile.label),
)
else:
connection = store.get(connection_id)
profile = profile_by_id(connection.profile_id)
if profile not in eligible_profiles():
raise ValueError(
f"connection is not eligible for read-only portfolios: {connection_id}"
)
if connection_id in seen_ids:
raise ValueError("portfolio connection ids must be unique")
label = str(raw.get("label") or connection.label).strip()View on GitHub (pinned to 80ffdda44c)
Solutions
- Use a simple lowercase slug: letters, digits, hyphens/underscores, e.g. 'binance-main'
- Ensure each entry has a non-empty connection_id (or id) key
- Check _SOURCE_ID_RE in agent/src/portfolio/config.py for the exact charset/length rules
Example fix
# before
{"connection_id": "Binance Main!!"}
# after
{"connection_id": "binance-main"} Defensive patterns
Strategy: validation
Validate before calling
import re
_SOURCE_ID_RE = re.compile(r'^[a-z0-9][a-z0-9_-]*$') # mirror the library's pattern
cid = str(entry.get('connection_id') or entry.get('id') or '').strip().lower()
if not _SOURCE_ID_RE.fullmatch(cid):
entry['connection_id'] = slugify(cid) Type guard
def is_valid_source_id(cid) -> bool:
return isinstance(cid, str) and bool(re.fullmatch(r'[a-z0-9][a-z0-9_-]*', cid.strip().lower())) Try / catch
try:
settings = parse_settings(payload, store)
except ValueError as exc:
if 'invalid portfolio connection id' in str(exc):
for e in payload['sources']:
e['connection_id'] = slugify(e.get('connection_id') or e.get('id') or '')
settings = parse_settings(payload, store) Prevention
- Generate ids with a slugify function (lowercase, hyphens, no specials)
- Always include connection_id (or legacy id) in every source entry
- Mirror the library's regex in upstream form validation
When it happens
Trigger: Ids containing uppercase (lowered first), spaces, slashes, special characters, or an entirely missing connection_id/id key; also ids exceeding whatever length/charset _SOURCE_ID_RE mandates.
Common situations: Copy-pasting exchange account URIs or emails as ids, omitting connection_id and only providing profile_id, or trailing whitespace/punctuation from manual editing.
Related errors
- max_bytes must be positive, got {max_bytes}
- display_currency must be USD or CNY
- sources must be a list
- at most 50 portfolio sources are allowed
- each portfolio source must be an object
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/a695df475556f425.
Report an issue: GitHub.