Hmbown/CodeWhale · error · RuntimeCapabilityError

thread_event_progress

thread_event_progress

Error message

Runtime does not support thread replay progress

What it means

When includeProgress is requested, threadEvents() checks the x-codewhale-event-progress response header. If the runtime does not advertise progress support (header is not "1"), it cancels the stream and throws RuntimeCapabilityError with code thread_event_progress and status 501. This means the connected runtime version does not implement thread replay progress markers.

Solutions

  1. Upgrade the Codewhale runtime to a version supporting thread replay progress.
  2. Drop includeProgress: true and consume the stream without progress markers.
  3. Feature-detect first: catch RuntimeCapabilityError with code 'thread_event_progress' and retry without the flag.

Example fix

// before
for await (const ev of client.threadEvents(id, { includeProgress: true })) handle(ev);
// after
async function replay(id, wantProgress) {
  try {
    for await (const ev of client.threadEvents(id, { includeProgress: wantProgress })) handle(ev);
  } catch (err) {
    if (err?.code === "thread_event_progress") return replay(id, false);
    throw err;
  }
}
Defensive patterns

Strategy: fallback

Try / catch

async function replay(id, wantProgress = true) { try { for await (const ev of client.threadEvents(id, { includeProgress: wantProgress })) handle(ev); } catch (err) { if (err?.code === "thread_event_progress") return replay(id, false); throw err; } }

Prevention

When it happens

Trigger: client.threadEvents(id, { includeProgress: true }) against a runtime whose /v1/threads/:id/events endpoint omits x-codewhale-event-progress: 1.

Common situations: Older runtime deployed in staging/production while the client was built against a newer one; connecting a local dev SDK to a minimal or third-party runtime implementation.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/c61cedb2d61343e3. Report an issue: GitHub.

Appendix: source

Thrown at npm/runtime-sdk/index.js:149

      if (value === undefined) continue;
      if (!Number.isSafeInteger(value) || value < 0) throw new TypeError(`${key} must be a nonnegative safe integer`);
      query.set(key, String(value));
    }
    if (options.includeProgress !== undefined && typeof options.includeProgress !== "boolean")
      throw new TypeError("includeProgress must be a boolean");
    if (options.includeProgress) query.set("progress", "true");
    const path = `/v1/threads/${segment(threadId)}/events?${query}`;
    const response = await this.#rawRequest(path, {
      method: "GET", capability: "thread_event_stream", accept: "text/event-stream",
      signal: options.signal, redirect: "error",
    });
    if (!response.body || !/^text\/event-stream(?:;|$)/i.test(response.headers.get("content-type") ?? "")) {
      await response.body?.cancel();
      throw new RuntimeApiError("Runtime thread response is not an event stream", { method: "GET", path });
    }
    if (options.includeProgress && response.headers.get("x-codewhale-event-progress") !== "1") {
      await response.body.cancel();
      throw new RuntimeCapabilityError("thread_event_progress", "Runtime does not support thread replay progress", { method: "GET", path, status: 501 });
    }
    yield* parseEventStream(response.body, { maxFrameChars: 2 * 1024 * 1024, requireBoundary: true });
  }

  async #jsonRequest(path, options = {}) {
    const response = await this.#rawRequest(path, options);
    if (response.status === 204) {
      return null;
    }
    return response.json();
  }

  async #rawRequest(path, options = {}) {
    const method = options.method ?? "GET";
    const headers = new Headers(options.headers);
    headers.set("accept", options.accept ?? "application/json");
    if (this.token) {
      headers.set("authorization", `Bearer ${this.token}`);

View on GitHub (pinned to 433685b202)