Skip to content

temporal-spring-ai: guard large media byte[] from entering workflow history#2860

Merged
donald-pinckney merged 5 commits intomasterfrom
spring-ai/media-size-guard
Apr 23, 2026
Merged

temporal-spring-ai: guard large media byte[] from entering workflow history#2860
donald-pinckney merged 5 commits intomasterfrom
spring-ai/media-size-guard

Conversation

@donald-pinckney
Copy link
Copy Markdown
Contributor

What was changed

  • ChatModelTypes.checkMediaSize(byte[]) — new helper that throws a non-retryable ApplicationFailure (failure type "MediaSizeExceeded") when a Media.data byte array exceeds the MAX_MEDIA_BYTES_IN_HISTORY threshold (default 1 MiB, overridable with the io.temporal.springai.maxMediaBytes system property; 0 disables).
  • ActivityChatModel.toMediaContent(...) and ChatModelActivityImpl.fromMedia(...) call the guard on both directions of the activity boundary so oversized payloads are rejected at the point of serialization instead of deep inside a gRPC failure.
  • README gains a "Media in messages" section documenting the cap, the override property, and the URI alternative.
  • MediaSizeGuardTest — unit tests on the helper plus integration tests using TestWorkflowEnvironment that verify (1) oversized UserMessage media fails the workflow with the guard error, (2) small media passes, (3) URI-based media passes regardless of would-be size, and (4) assistant-echoed oversized media fails the activity on the return path.

Why?

Raw media bytes on UserMessage / AssistantMessage get serialized into every relevant history event. Temporal's default per-event payload limit is 2 MiB; a single 5 MB PNG silently produces a cryptic gRPC failure at workflow runtime. Failing fast at the serialization edge, with a non-retryable ApplicationFailure whose message points at the URI-based constructor, turns a mystery failure into an obvious fix.

The guard uses a non-retryable ApplicationFailure instead of IllegalArgumentException so it fails the workflow / activity immediately rather than triggering indefinite workflow-task retries. This is a permanent, programmer-level error; retrying the same oversized payload will never succeed.

donald-pinckney and others added 3 commits April 21, 2026 15:56
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…istory

ChatModelTypes.checkMediaSize() rejects Media byte[] payloads larger than
1 MiB (default, overridable via the 'io.temporal.springai.maxMediaBytes'
system property) with a non-retryable ApplicationFailure pointing users
at the URI-based Media constructor. ActivityChatModel.toMediaContent
and ChatModelActivityImpl.fromMedia call the guard on both directions
of the activity boundary.

The guard throws a non-retryable ApplicationFailure — not a plain
IllegalArgumentException — because this is a permanent, programmer-level
error. Throwing a RuntimeException would cause the workflow task to be
retried forever (or the activity to churn through its maxAttempts)
rather than surfacing the real problem.

README gains a "Media in messages" section documenting the cap, the
override property, and the URI alternative.

Tests: MediaSizeGuardTest covers the helper directly (unit), plus
inbound/outbound activity-boundary paths via TestWorkflowEnvironment:
- oversized user-message media fails the workflow with the guard error
- small media passes through
- URI-based media passes regardless of would-be size
- assistant-echoed oversized media fails the activity

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Planning scratchpad — not part of the shipped artifact. Removed before merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@donald-pinckney donald-pinckney marked this pull request as ready for review April 22, 2026 19:52
@donald-pinckney donald-pinckney requested a review from a team as a code owner April 22, 2026 19:52
@donald-pinckney donald-pinckney enabled auto-merge (squash) April 23, 2026 20:30
@donald-pinckney donald-pinckney merged commit 64d5b2e into master Apr 23, 2026
17 checks passed
@donald-pinckney donald-pinckney deleted the spring-ai/media-size-guard branch April 23, 2026 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants