HKUDS/Vibe-Trading · error · ValueError
connection is not eligible for read-only portfolios: {connec
Error message
connection is not eligible for read-only portfolios: {connection_id} What it means
Every portfolio source connection must resolve to a profile that is in eligible_profiles() — i.e. profiles permitted to back read-only portfolio data. Using a connection tied to a trade-oriented or otherwise ineligible profile raises this error.
Source
Thrown at agent/src/portfolio/config.py:178
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()
if (
not label
or len(label) > 80
or any(ord(character) < 32 for character in label)
):
raise ValueError(
"portfolio source labels must contain 1 to 80 printable characters"
)
seen_ids.add(connection_id)
sources.append(
PortfolioSource(
connection_id=connection_id,
label=label,View on GitHub (pinned to 80ffdda44c)
Solutions
- Use a connection created from a read-only eligible profile (see eligible_profiles())
- Re-key the API connection with view-only permissions and recreate the connection
- Update the profile definition if it should be eligible, keeping security review in mind
Example fix
# before
{"connection_id": "binance-main", "profile_id": "full-trade"}
# after
{"connection_id": "binance-readonly", "label": "Binance (view only)"} Defensive patterns
Strategy: validation
Validate before calling
from agent.src.profiles import eligible_profiles
conn = store.get(cid)
eligible = {p.id for p in eligible_profiles()}
if conn.profile_id not in eligible:
raise PermissionError(f'{cid} uses an ineligible profile; pick a read-only profile') Type guard
def connection_is_eligible(store, cid) -> bool:
return store.get(cid).profile_id in {p.id for p in eligible_profiles()} Try / catch
try:
settings = parse_settings(payload, store)
except ValueError as exc:
if 'not eligible' in str(exc):
drop_ineligible_sources(payload)
settings = parse_settings(payload, store) # degraded, warn user Prevention
- Create dedicated read-only connections for portfolio sources
- Check eligible_profiles() when onboarding a connection for portfolio use
- Re-validate configs after profile eligibility rules change on upgrade
When it happens
Trigger: Referencing a connection whose profile_id maps to a trade profile; a legacy profile_id entry whose migrated profile is discovery-only or trade; tests asserting that discovery-only profiles cannot back a source hit exactly this branch.
Common situations: Migrating old configs where profile_id connections were auto-mapped, enabling a trade-capable API key for portfolio reads, or profile eligibility changing between releases.
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/69e97c9a870945e4.
Report an issue: GitHub.