HTTP success needs a status check and a decoder
Schema defines accepted values and checks data at runtime. An adapter implements an application interface for a provider.¶
A fulfilled HTTP request is not proof of application success.
Check the status and decode the body before passing provider data into the application.
Use the effect/http modules.¶
Check the protocol response
The deployment checker decodes tool discovery through ToolsResponse.
It also requires status 200 and the expected tool names.¶
const document =
yield* HttpClientResponse.schemaBodyJson(ToolsResponse)(response);
return (
response.status === 200 &&
["search", "read", "execute"].every((name) =>
document.result.tools.some((tool) => tool.name === name)
)
);
})Use the in-memory fixture below when learning.¶
Reject an unacceptable response before trusting its data
HttpClient.filterStatusOk accepts 2xx status codes.
An adapter can require a narrower status when its protocol needs one.
The fixture applies the filter before decoding a version response.¶
const client = (yield* HttpClient.HttpClient).pipe(
HttpClient.filterStatusOk
);
const response = yield* client
.get("https://provider.example.test/version")
.pipe(
Effect.mapError(
(cause) => new ResponseFixtureError({ cause, phase: "status" })
)
);
return yield* HttpClientResponse.schemaBodyJson(Reply)(response).pipe(
Effect.mapError(
(cause) => new ResponseFixtureError({ cause, phase: "body" })
)
);
}schemaBodyJson handles JSON parsing and schema decoding17. ResponseFixtureError retains the cause and names the failed phase.¶
The fixture groups request and status failures into its status phase.
It groups parsing and schema failures into its body phase.
A production adapter should choose failure names that match its job and repair path.¶
Supply the transport in tests
The test supplies a client that creates responses in memory. It does not start an HTTP server or call a provider.¶
Effect.sync(() =>
HttpClientResponse.fromWeb(
request,
new Response(scenario.body, {
headers: { "content-type": "application/json" },
status: scenario.status,
})
)
)
);
const result = yield* readValidatedResponse().pipe(
Effect.provideService(HttpClient.HttpClient, client),
Effect.result
);
| Simulated response | Required outcome |
|---|---|
| 200, integer version | Decoded version |
| 503, otherwise valid body | Named status-phase failure |
| 200, malformed JSON | Named body-phase failure |
| 200, string instead of integer | Named body-phase failure |
These tests of the HTTP client interface establish the fixture’s status and decoding policy. Check live endpoint health separately.¶
Decide whether replay is safe before adding retries
A transient failure may be temporary. retryTransient can retry transient responses and errors.
Its classification does not prove that repeating an operation is safe.
A write can complete remotely even when its response is lost.¶
Before retrying a write:¶
- Identify the operation’s replay or idempotency guarantee: whether repeating it can create a second change.¶
- Decide which failures allow another attempt.¶
- Measure the retry budget, the allowed attempts or time, and select the schedule.¶
- Preserve the final named failure when the budget ends.¶
Do not copy example delays or retry counts into production as measured limits. The fixture establishes no production retry budget.¶
Common mistakes
- Treat fulfilled fetch as success despite a failed status.¶
- Trust an object because JSON parsing succeeded.¶
- Replace the whole adapter in a test and stop exercising its decoder.¶
- Retry a write only because the transport calls its error transient.¶
Effect idiom and house rule
- Supply
HttpClient, compose request policies, decode responses, and translate failures at the adapter’s interface with the provider.¶ - In rat-stack, core owns service interfaces named for application jobs. Provider clients remain in adapters under hexagonal architecture19.¶
- In rat-stack, machines own finite retry lifecycles20. Effect also has native schedules and retry operators.¶
Read schemas17 and failures36 before defining the adapter’s accepted data. Then read tracing7 to observe the operation without exposing private values. Return to the Effect reading order17.¶
Sources
- Effect contributors. 2026. HttpClient. Effect 4.0.0.. Effect-TS. filterStatusOk rejects non-2xx responses; retryTransient classifies retryable errors and responses but does not establish application replay safety. Accessed 2026-10-06.
- Effect contributors. 2026. HttpClientResponse.. Effect-TS. schemaBodyJson parses a JSON response and decodes it through the supplied Schema. Accessed 2026-10-06.
- Effect contributors. 2026. Getting started with HttpClient.. Effect-TS. Supplied clients, request middleware, response decoding, named adapter errors, and request construction. Accessed 2026-10-06.
- rat-stack contributors. 2026. Deployment behavior checks.. rat-stack. A protocol check validates response status and schema-decoded tool discovery before reporting behavior-confirmed. Accessed 2026-10-06.
- rat-stack contributors. 2026. HTTP response fixture.. rat-stack. A supplied in-memory client exercises valid data, non-2xx status, malformed JSON, and a wrong decoded field type. Accessed 2026-10-06.
- Langton, Kit. 2026. HTTP Clients. Effect Solutions.. Kit Langton. The draft frames middleware and response decoding. This guide uses exact stable-version source and independent fixtures. Accessed 2026-10-06.
Last changed 2026-10-07 in f1a00f2. Source on GitHub. Change log.
Linked from
- Agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
HTTP success needs a status check and a decoder — Supply the client, check the response status, decode accepted data, and name failures at the adapter boundary.
- Change log. What changed in the files served here, newest first.
HTTP success needs a status check and a decoder — edited: feat(learn): teach cards 43 to 62 with plain lines, diagrams and snippets
- Concurrent work needs an owner and a bound. Limit active work, retain result order, and stop child work when its owning lifetime ends.
Next, validate HTTP responses before treating concurrent provider work as successful.
- Effect basics. An Effect describes work, expected failures, and required services before a runtime executes it.
HTTP responses: check status and decode accepted data.¶
- Full agent guide. An Effect stack so pure (aspirational) Kit Langton will blush.
- Rat Stack lore | rat-stack. Short, source-grounded notes on the ideas and decisions behind rat-stack.
HTTP success needs a status check and a decoder — Supply the client, check the response status, decode accepted data, and name failures at the adapter boundary.
- Source change history (log.md). The generated change log as Markdown.
HTTP success needs a status check and a decoder — edited: feat(learn): teach cards 43 to 62 with plain lines, diagrams and snippets
Unlinked mentions (1)
- add-a-store → Check replay and interrupted execution when the new operation promises idempotency or atomicity.¶
Content updated .