Skip to content

fix(evlog): do not log ErrorEvent from event stream response bodies - #1918

Merged
dinwwwh merged 1 commit into
middleapi:mainfrom
dinwwwh:claude/evlong-pino-error-event-logging-255a4c
Aug 22, 2026
Merged

fix(evlog): do not log ErrorEvent from event stream response bodies#1918
dinwwwh merged 1 commit into
middleapi:mainfrom
dinwwwh:claude/evlong-pino-error-event-logging-255a4c

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Aug 22, 2026

Copy link
Copy Markdown
Member

Business errors thrown from event iterator procedures were logged twice by EvlogHandlerPlugin: once correctly by the client interceptor, and again at error level by the routing interceptor's response body wrapper, because the codec encodes them as ErrorEvent for the wire and the wrapper treated every body error as an internal failure.

Fixes

  • Streamed business errors no longer produce a spurious internal-failure log at error level; the client interceptor's log (warn for ORPCError, info for aborts) is now the only record.
  • Genuine internal failures while streaming, ReadableStream body errors, and all pre-codec error paths are logged exactly as before.

Testing

  • New test throws ORPCError from an event iterator, encodes it through the real RPCSerializer, and asserts nothing is logged while the wide event still finishes with the response status.

The routing interceptor's response body wrapper logged every error as an
internal failure, but the codec encodes business errors (e.g. ORPCError)
thrown from event iterators as ErrorEvent for the wire, so each streamed
business error was logged twice: once correctly by the client interceptor
and again at error level as a bogus internal failure.
@vercel

vercel Bot commented Aug 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
orpc Ready Ready Preview Aug 22, 2026 2:44am

@pkg-pr-new

pkg-pr-new Bot commented Aug 22, 2026

Copy link
Copy Markdown
More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@1918

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@1918

@orpc/bun

npm i https://pkg.pr.new/@orpc/bun@1918

@orpc/client

npm i https://pkg.pr.new/@orpc/client@1918

@orpc/cloudflare

npm i https://pkg.pr.new/@orpc/cloudflare@1918

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@1918

@orpc/experimental-effect

npm i https://pkg.pr.new/@orpc/experimental-effect@1918

@orpc/evlog

npm i https://pkg.pr.new/@orpc/evlog@1918

@orpc/hibernation

npm i https://pkg.pr.new/@orpc/hibernation@1918

@orpc/json-schema

npm i https://pkg.pr.new/@orpc/json-schema@1918

@orpc/experimental-msw

npm i https://pkg.pr.new/@orpc/experimental-msw@1918

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@1918

@orpc/next

npm i https://pkg.pr.new/@orpc/next@1918

@orpc/node

npm i https://pkg.pr.new/@orpc/node@1918

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@1918

@orpc/opentelemetry

npm i https://pkg.pr.new/@orpc/opentelemetry@1918

@orpc/pinia-colada

npm i https://pkg.pr.new/@orpc/pinia-colada@1918

@orpc/pino

npm i https://pkg.pr.new/@orpc/pino@1918

@orpc/publisher

npm i https://pkg.pr.new/@orpc/publisher@1918

@orpc/ratelimit

npm i https://pkg.pr.new/@orpc/ratelimit@1918

@orpc/server

npm i https://pkg.pr.new/@orpc/server@1918

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@1918

@orpc/swr

npm i https://pkg.pr.new/@orpc/swr@1918

@orpc/tanstack-query

npm i https://pkg.pr.new/@orpc/tanstack-query@1918

@orpc/trpc

npm i https://pkg.pr.new/@orpc/trpc@1918

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@1918

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@1918

commit: 166eb79

@codecov

codecov Bot commented Aug 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 30 untouched benchmarks


Comparing dinwwwh:claude/evlong-pino-error-event-logging-255a4c (166eb79) with main (519c3f2)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (3078b1c) during the generation of this report, so 519c3f2 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No critical issues — minor suggestions inline.

Reviewed changes

  • packages/evlog/src/handler-plugin.ts — guard the routing interceptor's stream onError so an ErrorEvent (the codec's wire-encoding of a thrown iterator error) no longer produces a spurious internal-failure error log.
  • packages/evlog/src/handler-plugin.test.ts — new test throws ORPCError from an event iterator, serializes via the real RPCSerializer, and asserts nothing is logged at error level while the stream still finishes with status 200.

The core fix is sound: RPCSerializer.serialize (packages/client/src/rpc-serializer.ts:59) converts every source-iterator error — business or internal — into an ErrorEvent via toORPCError, and the plugin's clientInterceptor already logs all of those at error/warn/info. So the routing wrapper's onError was a duplicate for the standard procedure path, and skipping ErrorEvent there is correct.

One inline note on the comment/scope and one nitpick on the test's coverage.

ℹ️ Nitpicks

  • The new comment describes ErrorEvent as strictly "a business error ... already logged by the client interceptor." Because RPCSerializer wraps any thrown iterator error into an ErrorEvent, the guard is broader than that rationale implies — worth tightening the wording so future readers don't rely on the narrow claim.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Comment on lines +102 to +107
* Errors here are internal (interceptor/framework) failures,
* except `ErrorEvent`: a business error the protocol delivers
* inside the event stream, already logged by the client interceptor.
*/
logger.error(toErrorOrString(error))
if (!(error instanceof ErrorEvent)) {
logger.error(toErrorOrString(error))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor scope note: an ErrorEvent is not strictly a business error. RPCSerializer.serialize's mapError (packages/client/src/rpc-serializer.ts:59) wraps any error thrown from the source iterator via toORPCError into an ErrorEvent — internal failures included. Suppression here is correct in practice only because the plugin's clientInterceptor (logBusinessLogicError, lines 258-272) already logs every iterator error from the procedure path first (error for non-ORPCError, warn for ORPCError, info for aborts). The residual gap is narrow: an error thrown while succeeding a yielded stream value during serialization (a codec transform failure) is wrapped into ErrorEvent above the client-interceptor wrap, so it is no longer error-logged here. Consider rewording the comment to say the guard suppresses the protocol's serialized error envelope rather than "a business error".

@dinwwwh
dinwwwh merged commit a9b4f2e into middleapi:main Aug 22, 2026
12 checks passed
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.

1 participant