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

  1. Use a connection created from a read-only eligible profile (see eligible_profiles())
  2. Re-key the API connection with view-only permissions and recreate the connection
  3. 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

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


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/69e97c9a870945e4. Report an issue: GitHub.