Hmbown/CodeWhale · error · RuntimeCapabilityError

Runtime API capability '${options.capability}' is not availa

Error message

Runtime API capability '${options.capability}' is not available at ${method} ${path}

What it means

Thrown as RuntimeCapabilityError by CodeWhaleRuntimeClient (npm/runtime-sdk) when a capability-tagged fleet endpoint answers HTTP 404, 405, or 501. It means the runtime server behind baseUrl (default http://127.0.0.1:7878) does not implement that capability, most often because the runtime binary and the SDK are at different versions. The error carries .capability, .status, .method, .path and the response .body for diagnosis. Only createFleetRun (fleet_run_create), startFleetRun (fleet_run_start), replayFleetEvents (fleet_event_replay), and the fleetEvents stream (fleet_event_stream) set a capability; other routes surface as plain RuntimeApiError.

Source

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

    headers.set("accept", options.accept ?? "application/json");
    if (this.token) {
      headers.set("authorization", `Bearer ${this.token}`);
    }
    const init = { method, headers };
    if (options.body !== undefined) {
      headers.set("content-type", "application/json");
      init.body = JSON.stringify(options.body);
    }

    const response = await this.fetchImpl(new URL(path, this.baseUrl), init);
    if (response.ok) {
      return response;
    }

    const body = await readErrorBody(response);
    const errorOptions = { status: response.status, method, path, body };
    if (options.capability && [404, 405, 501].includes(response.status)) {
      throw new RuntimeCapabilityError(
        options.capability,
        `Runtime API capability '${options.capability}' is not available at ${method} ${path}`,
        errorOptions,
      );
    }
    throw new RuntimeApiError(
      `Runtime API request failed (${response.status}) for ${method} ${path}`,
      errorOptions,
    );
  }
}

export function createRuntimeClient(options = {}) {
  return new CodeWhaleRuntimeClient(options);
}

function normalizeBaseUrl(value) {
  return value.endsWith("/") ? value : `${value}/`;

View on GitHub (pinned to 8880682c63)

Solutions

  1. Read err.capability, err.status and err.path, then bring the Codewhale runtime to a version that implements that capability (align runtime and SDK versions)
  2. Confirm createRuntimeClient({ baseUrl }) points directly at the runtime port (default 127.0.0.1:7878) and no proxy strips or rewrites /v1/fleet/* paths
  3. Reproduce manually with the method/path from the message and inspect the response body to see whether a gateway or the runtime itself answered
  4. If the capability is optional in your integration, catch RuntimeCapabilityError and degrade gracefully instead of failing the whole run

Example fix

// before
const run = await client.createFleetRun(spec); // crashes with RuntimeCapabilityError against an old runtime

// after
import { RuntimeCapabilityError } from "@codewhale/runtime-sdk";
try {
  const run = await client.createFleetRun(spec);
} catch (error) {
  if (error instanceof RuntimeCapabilityError) {
    console.error(
      `Runtime lacks ${error.capability} (HTTP ${error.status} on ${error.method} ${error.path}); upgrade the runtime binary to match this SDK`,
    );
  }
  throw error;
}
Defensive patterns

Strategy: try-catch

Validate before calling

async function runtimeHasFleetApi(client) {
  const response = await client.fetchImpl(new URL("/v1/fleet/runs", client.baseUrl), {
    method: "GET",
    headers: { accept: "application/json" },
  });
  return response.ok || response.status === 405;
}

Type guard

import { RuntimeCapabilityError } from "@codewhale/runtime-sdk";
function isRuntimeCapabilityError(error) {
  return error instanceof RuntimeCapabilityError || error?.name === "RuntimeCapabilityError";
}

Try / catch

try {
  await client.startFleetRun(runId);
} catch (error) {
  if (isRuntimeCapabilityError(error) && [404, 405, 501].includes(error.status)) {
    // capability unavailable: upgrade the runtime or disable this code path
    return handleUnsupportedCapability(error.capability);
  }
  throw error;
}

Prevention

When it happens

Trigger: POST /v1/fleet/runs, POST /v1/fleet/runs/{id}/start, GET|POST /v1/fleet/runs/{id}/events/replay, or GET /v1/fleet/runs/{id}/events (accept: text/event-stream) responding 404, 405, or 501 while options.capability is set in #rawRequest.

Common situations: SDK upgraded ahead of the runtime binary (or an old runtime pinned in Docker/CI); baseUrl pointing at a proxy or gateway that rewrites fleet paths into 404s; a runtime build with the fleet API disabled or compiled out; middleware answering 501 for unknown methods.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/85e6e2f69f8a91c0. Report an issue: GitHub.