{"record":{"id":"3ee5af3876d3d787","repo":"HKUDS/Vibe-Trading","slug":"portfolio-source-labels-must-contain-1-to-80-print","errorCode":null,"errorMessage":"portfolio source labels must contain 1 to 80 printable characters","messagePattern":"portfolio source labels must contain 1 to 80 printable characters","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/portfolio/config.py","lineNumber":189,"sourceCode":"                legacy_profile.id,\n                str(raw.get(\"label\") or legacy_profile.label),\n            )\n        else:\n            connection = store.get(connection_id)\n        profile = profile_by_id(connection.profile_id)\n        if profile not in eligible_profiles():\n            raise ValueError(\n                f\"connection is not eligible for read-only portfolios: {connection_id}\"\n            )\n        if connection_id in seen_ids:\n            raise ValueError(\"portfolio connection ids must be unique\")\n        label = str(raw.get(\"label\") or connection.label).strip()\n        if (\n            not label\n            or len(label) > 80\n            or any(ord(character) < 32 for character in label)\n        ):\n            raise ValueError(\n                \"portfolio source labels must contain 1 to 80 printable characters\"\n            )\n        seen_ids.add(connection_id)\n        sources.append(\n            PortfolioSource(\n                connection_id=connection_id,\n                label=label,\n                enabled=bool(raw.get(\"enabled\", True)),\n                order=int(raw.get(\"order\", index)),\n                include_cash=bool(raw.get(\"include_cash\", True)),\n            )\n        )\n    return PortfolioSettings(\n        display_currency=currency,\n        sources=tuple(sorted(sources, key=lambda item: (item.order, item.id))),\n    )\n\n","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/portfolio/config.py#L171-L207","documentation":"Each source's label (explicit or inherited from the connection) must be 1-80 characters with no control characters (< 0x20). Empty, over-length, or control-character labels are rejected during parsing.","triggerScenarios":"label = '', '   ' (after strip), an 81+ character label, labels containing '\\n'/'\\t'/null bytes, or a connection whose stored label is blank so the fallback fails too.","commonSituations":"Omitting labels assuming defaults exist, pasting multi-line text into a label field, unicode paste introducing control chars, or scripted configs generating labels from unbounded strings.","solutions":["Set a concise label (1-80 printable characters)","Truncate generated labels: label[:80]","Strip control characters from pasted text before saving"],"exampleFix":"# before\n{\"connection_id\": \"binance-main\", \"label\": \"\"}\n# after\n{\"connection_id\": \"binance-main\", \"label\": \"Binance main account\"}","handlingStrategy":"validation","validationCode":"label = ''.join(ch for ch in (label or '').strip() if ord(ch) >= 32)[:80]\nif not label:\n    label = cid  # fallback to the connection id itself\nentry['label'] = label","typeGuard":"def is_valid_label(label) -> bool:\n    return bool(label) and len(label) <= 80 and all(ord(c) >= 32 for c in label)","tryCatchPattern":"try:\n    settings = parse_settings(payload, store)\nexcept ValueError as exc:\n    if 'labels must contain' in str(exc):\n        for e in payload['sources']:\n            e['label'] = sanitize_label(e.get('label')) or (e.get('connection_id') or 'source')\n        settings = parse_settings(payload, store)","preventionTips":["Always set explicit labels when generating source entries","Truncate generated labels to 80 chars","Strip pasted control characters before saving"],"tags":["python","config","validation","label"],"backgroundTag":"invalid-config-value","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}