Skip to content

Widespread use of as any in core runtime paths masks type errors and enables runtime crashes #3715

@AseemPrasad

Description

@AseemPrasad

Why do you want to contribute?

Widespread use of as any in core runtime paths masks type errors and enables runtime crashes**

  • Files / functions involved (representative samples)

    • ai.ts — many as any casts across message/part processing (see ai.ts)
    • chat-react.ts — casts around streaming parts/IDs (see chat-react.ts)
    • queue.ts and other core packages and webapp components (many as any occurrences found by grep)
    • Tests also use as any heavily (examples: packages/trigger-sdk/test/*.test.ts, apps/webapp/test/*.test.ts)
  • Root cause

    • Developers have used as any to bypass TypeScript checks in numerous hot paths (message parsing, parts handling, SDK internal APIs). This removes compile-time guarantees and hides potential runtime mismatches between expected shapes and actual input. Where external inputs are deserialized (JSON, streams, SDK payloads), missing runtime validation combined with as any leads to:
      • Uncaught runtime exceptions (e.g., accessing properties that don't exist).
      • Subtle logic errors when shape assumptions are violated.
      • Hard-to-debug failures in user-facing SDKs or server code.
  • Steps to reproduce (example)

    1. Identify a code path that casts an unvalidated object to any and then accesses nested properties (e.g. a streaming chunk in ai.ts).
    2. Send a malformed message (missing expected parts or with unexpected types).
    3. The code will attempt property access and may throw an exception at runtime (which may not be surfaced or be logged cryptically because of broad catch blocks).
  • Expected vs actual

    • Expected: message/part streams and external inputs are validated (Zod or TypeScript-checked shapes), and errors are handled gracefully with clear logs and fallback behavior.
    • Actual: as any bypasses validation; code assumes shapes leading to fragile runtime behavior.
  • Suggested fix (implementation details)

    • Add runtime validation at public/edge boundaries:

      • Use Zod schemas (already used in many places) to validate incoming messages/parts before casting to expected types.
      • Replace as any in critical code paths with typed helper functions or strongly-typed discriminated unions.
    • Gradual refactor plan:

      1. Identify the most critical hotspots (message ingestion / streaming / SDK public surfaces). The grep shows concentrated as any usage in ai.ts and chat-react.ts — start there.
      2. Add small runtime validators (Zod) and unit tests that exercise malformed inputs to check graceful failure and logging.
      3. Introduce an ESLint rule in the repo to disallow as any in packages/* and apps/* except for narrow, justified exceptions. Enforce later with CI.
    • Tests:

      • Add unit tests feeding malformed parts/messages and asserting the function returns a deterministic error path or sanitized output (no crash).
      • Add type-level tests where possible.
    • The task can be done incrementally: fix a few critical files and add tests; then extend rules to the rest of the codebase.

    • Short-term mitigation: add runtime guards around the top 3-5 hotspots.

    • There are many tests, but they assume well-formed inputs and use as any themselves. There are no explicit negative tests that feed malformed external input for these message/parts pipelines. So coverage is partial-to-missing for malformed-input scenarios.

Prior contributions or relevant experience

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions