Skip to content

Cancel oversized provider response bodies rejected by Content-Length #39

Closed

Description

@haseebahmed248

Problem

The provider adapter rejects an oversized Content-Length without cancelling the response body. It then clears its timeout and removes the runtime abort listener, leaving the unread stream without cleanup from this adapter.

Reproduced on main at f5db6e2 and installed guardstep@0.1.0-alpha.1 with an injected fetch implementation. No external service or API key is required.

Reproduction

Run this in a project with the package installed:

import { createOpenAICompatibleModelAdapter } from "guardstep/providers";

let cancelled = false;
let fetchSignal;
const adapter = createOpenAICompatibleModelAdapter({
  baseUrl: "http://localhost:11434/v1",
  profiles: { test: { model: "test" } },
  maxResponseBytes: 10,
  timeoutMs: 20,
  fetch: async (_url, options) => {
    fetchSignal = options.signal;
    return new Response(new ReadableStream({
      cancel() { cancelled = true; },
    }), { headers: { "content-length": "1000" } });
  },
});
const result = await adapter.generate({
  runId: "review", stepId: "generate", profile: "test",
  instructions: "Return JSON", context: {},
  outputSchema: { type: "object" },
  signal: new AbortController().signal,
});
console.log(result, cancelled, fetchSignal.aborted);

The result is PROVIDER_RESPONSE_TOO_LARGE, but both cancelled and fetchSignal.aborted are false. Waiting beyond the timeout leaves them false.

Starting point

packages/guardstep/src/providers/openai-compatible.ts, readResponseText: the early header check returns before obtaining a reader. The streamed-size-limit branch already calls reader.cancel().

Acceptance criteria

  • Cancel the unread body or abort the request when rejecting the declared size.
  • Add a regression test using an injected response stream and a cancellation/abort spy.
  • Keep the public failure code PROVIDER_RESPONSE_TOO_LARGE and avoid including provider response content in errors.
  • Preserve existing streamed-size-limit and timeout behavior.

Activity

  1. kudala-bharani commented on Sep 5, 2026

    @kudala-bharani
    Contributor

    I'll take this. I'll add cancellation to the early Content-Length rejection and a regression test with an injected response stream, preserving the existing failure code and streamed-size/timeout behavior.

  2. haseebahmed248 commented on Sep 6, 2026

    @haseebahmed248
    OwnerAuthor

    Assigned to you, @kudala-bharani. Thanks for sending #43 with regression tests. I've left one review comment about pending cancellation on the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workinggood first issueGood for newcomers

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions