HKUDS/Vibe-Trading · error · ValueError

instrument_id is required and cannot be empty

Error message

instrument_id is required and cannot be empty

What it means

Instrument.__post_init__ requires a non-empty instrument_id after stripping. If instrument_id is not a str (or is whitespace-only), cleaned becomes '' and the constructor raises, because an instrument cannot be identified without an id.

Source

Thrown at agent/src/entities/models.py:214

    instrument_id: str
    currency: str
    name: str = ""
    issuer: Entity | None = None
    inception_date: date | None = None

    def __post_init__(self) -> None:
        """Validate the identifier and normalize currency and inception date.

        Raises:
            ValueError: If ``instrument_id`` is blank, the currency is invalid,
                or ``inception_date`` is not a supported date value.
        """
        cleaned = (
            self.instrument_id.strip() if isinstance(self.instrument_id, str) else ""
        )
        if not cleaned:
            raise ValueError("instrument_id is required and cannot be empty")
        object.__setattr__(self, "instrument_id", cleaned)
        object.__setattr__(self, "currency", normalize_currency(self.currency))
        object.__setattr__(self, "name", self.name.strip() if self.name else "")
        if self.inception_date is not None:
            object.__setattr__(
                self,
                "inception_date",
                normalize_date(self.inception_date, field_name="inception_date"),
            )


@dataclass(frozen=True)
class Security(Instrument):
    """A listed security identified by a ticker on a venue.

    A ``Security`` here is the *reference* record only. Its price history still
    belongs to the bar-based loader path; this class exists so a corporate
    action or a dividend stream can be attached to a named instrument.

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Check for a truthy, stripped id before constructing: row.get('symbol','').strip() and skip/log empty rows
  2. Fix data extraction so the id column is always a non-empty string
  3. Guard at ingest with a validation pass that reports which source rows lack ids

Example fix

# before
Instrument(instrument_id=row.get('ticker'), currency='USD')

# after
iid = (row.get('ticker') or '').strip()
if not iid:
    continue  # or log and skip
Instrument(instrument_id=iid, currency='USD')
Defensive patterns

Strategy: validation

Validate before calling

iid = row.get('instrument_id')
if not isinstance(iid, str) or not iid.strip():
    raise ValueError(f"row missing instrument_id: {row!r}")
inst = Instrument(instrument_id=iid, ...)

Type guard

def has_instrument_id(row: dict) -> bool:
    v = row.get('instrument_id')
    return isinstance(v, str) and bool(v.strip())

Try / catch

try:
    inst = Instrument(instrument_id=row['id'], ...)
except ValueError as exc:
    if 'instrument_id' in str(exc):
        log.warning('skipping row without instrument_id: %r', row)
        continue
    raise

Prevention

When it happens

Trigger: Instrument(instrument_id=''), Instrument(instrument_id=' '), or passing a non-string (None, int) — the isinstance check yields an empty cleaned string. Also occurs when a dict key is missing and .get() returns None.

Common situations: Parsing spreadsheets/CSVs where the ticker/id column has blank cells; a dict built with a typo'd key so the id field gets None; rows with only whitespace or placeholder dashes in the symbol column.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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