Skip to content

feat: introduce a typed StreamError dataclass for streaming error chunks #1780

@Pouyanpi

Description

@Pouyanpi

Error chunks are currently hand built JSON strings with inconsistent schemas across IORails and LLMRails (different fields, different type/code values, LLMRails includes "param" while IORails doesn't). The API consumer layer has no contract to parse against.

Worse, because errors are plain JSON strings, they're indistinguishable from LLM output and flow into RollingBuffer and get checked by output rails as content.

Fix: add a StreamError datamodel to a shared module. Both IORails and LLMRails construct StreamError objects instead of inline json.dumps. StreamingHandler yields them as typed objects. Consumer uses isinstance instead of JSON parsing heuristics. RollingBuffer skips them.

class StreamErrorDetails(BaseModel):
    message: str
    type: str
    code: str
    param: str | None = None # flow_id, when applicable

class StreamError(BaseModel):
    error: StreamErrorDetails

class StreamErrorType(str, Enum):
    GENERATION_ERROR = "generation_error"
    GUARDRAILS_VIOLATION = "guardrails_violation"
    INTERNAL_ERROR = "internal_error"

class StreamErrorCode(str, Enum):
    GENERATION_FAILED = "generation_failed"
    CONTENT_BLOCKED = "content_blocked"
    RAIL_EXECUTION_FAILURE = "rail_execution_failure"

The enums enforce consistent vocabulary. All existing call sites in both IORails and LLMRails need to be migrated to use these instead of inline strings. LLMRails extract_error_json() should also be updated to produce a StreamError with valid enum values rather than passing through arbitrary upstream error shapes.

Should land after #1766.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions