overengineeringstudio / overengineeringstudio/effect-utils
restate-effect: own the decode-error envelope instead of forwarding Effect's parser rendering
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 82
- Forks
- 2
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 121
Description
Problem
restate-effect leaks Effect's internal parser rendering into a caller-facing HTTP response.
classifyDecodeFailure embeds ParseResult.TreeFormatter.formatErrorSync(...) verbatim into a TerminalError(400):
const detail = ParseResult.isParseError(input.cause) === true
? ParseResult.TreeFormatter.formatErrorSync(input.cause)
: ...
return new restate.TerminalError(`serde decode failed: ${detail}`, { errorCode: 400 })
packages/@overeng/restate-effect/src/schema/Serde.ts:126-144, installed on public ingress calls and handler inputs via clients/InvocationPolicy.ts:107-126 and endpoint/Endpoint.ts:267.
That serde governs handler input/output, state, durable step results, awakeables, and durable promises — so the formatting of an upstream library's error object is, in effect, part of our public HTTP contract.
Why this matters independently of any upgrade
The rendering is not ours and can change without notice. Concretely, Effect 4 changes this exact text from a parse-tree rendering to SchemaError(...). Status and classification stay 400, but the response body changes, and any client, log pipeline, support tool, or assertion that stores or displays it observes the difference.
This was found while verifying an Effect 3 → 4 migration, but the coupling is the real defect: we would have the same exposure on any future upstream formatter change.
Proposed direction
Define a stable, first-party decode-error envelope owned by restate-effect:
- a stable error code
- the schema identifier / failing path
- a migration-independent human summary
and stop forwarding the framework's parser rendering to callers. Internal corrupt-journal defects can keep framework diagnostics, since those are not caller contracts.
Add an ingress test with invalid input that asserts the stable HTTP error body, so the contract is pinned rather than inherited.
Acceptance
-
restate-effectowns a documented decode-error envelope - no Effect-internal formatter output reaches a caller-facing response
- ingress test pins the error body for an invalid-input case
- internal/infrastructure failures keep full diagnostics
Posted on behalf of @schickling
| field | value |
|---|---|
agent_name |
cl1-heron |
agent_session_id |
54711470-ae7e-4322-a3e2-129a2689a097 |
agent_tool |
Claude Code |
agent_tool_version |
2.1.220 |
agent_runtime |
Claude Code 2.1.220 |
agent_model |
claude-opus-5 |
runtime_profile |
/nix/store/xg6r3nkr7spjyg2gbl3zprqbsag3fsjc-coding-agent-runtime-profile/share/coding-agents/profile.json |
skills_manifest |
/nix/store/2vkpfkkbc9hjmcwknzkv62v2i44an8mz-agent-skills-corpus/share/agent-skills/manifest.json |
worktree |
effect-utils/schickling/2026-07-28-effect-4 |
machine |
dev3 |
tooling_profile |
dotfiles@unknown-dirty |
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Read classifyDecodeFailure in packages/@overeng/restate-effect/src/schema/Serde.ts:126-144, then trace its use through clients/InvocationPolicy.ts:107-126 and endpoint/Endpoint.ts:267. Define the documented stable decode-error envelope and add the invalid-input ingress test described in the issue. Done means caller responses no longer expose Effect formatter output, while internal failures retain diagnostics.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100