{"record":{"id":"85e6e2f69f8a91c0","repo":"Hmbown/CodeWhale","slug":"runtime-api-capability-options-capability-is","errorCode":null,"errorMessage":"Runtime API capability '${options.capability}' is not available at ${method} ${path}","messagePattern":"Runtime API capability '(.+?)' is not available at (.+?) (.+?)","errorType":"exception","errorClass":"RuntimeCapabilityError","httpStatus":null,"severity":"error","filePath":"npm/runtime-sdk/index.js","lineNumber":156,"sourceCode":"    headers.set(\"accept\", options.accept ?? \"application/json\");\n    if (this.token) {\n      headers.set(\"authorization\", `Bearer ${this.token}`);\n    }\n    const init = { method, headers };\n    if (options.body !== undefined) {\n      headers.set(\"content-type\", \"application/json\");\n      init.body = JSON.stringify(options.body);\n    }\n\n    const response = await this.fetchImpl(new URL(path, this.baseUrl), init);\n    if (response.ok) {\n      return response;\n    }\n\n    const body = await readErrorBody(response);\n    const errorOptions = { status: response.status, method, path, body };\n    if (options.capability && [404, 405, 501].includes(response.status)) {\n      throw new RuntimeCapabilityError(\n        options.capability,\n        `Runtime API capability '${options.capability}' is not available at ${method} ${path}`,\n        errorOptions,\n      );\n    }\n    throw new RuntimeApiError(\n      `Runtime API request failed (${response.status}) for ${method} ${path}`,\n      errorOptions,\n    );\n  }\n}\n\nexport function createRuntimeClient(options = {}) {\n  return new CodeWhaleRuntimeClient(options);\n}\n\nfunction normalizeBaseUrl(value) {\n  return value.endsWith(\"/\") ? value : `${value}/`;","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/npm/runtime-sdk/index.js#L138-L174","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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)","Confirm createRuntimeClient({ baseUrl }) points directly at the runtime port (default 127.0.0.1:7878) and no proxy strips or rewrites /v1/fleet/* paths","Reproduce manually with the method/path from the message and inspect the response body to see whether a gateway or the runtime itself answered","If the capability is optional in your integration, catch RuntimeCapabilityError and degrade gracefully instead of failing the whole run"],"exampleFix":"// before\nconst run = await client.createFleetRun(spec); // crashes with RuntimeCapabilityError against an old runtime\n\n// after\nimport { RuntimeCapabilityError } from \"@codewhale/runtime-sdk\";\ntry {\n  const run = await client.createFleetRun(spec);\n} catch (error) {\n  if (error instanceof RuntimeCapabilityError) {\n    console.error(\n      `Runtime lacks ${error.capability} (HTTP ${error.status} on ${error.method} ${error.path}); upgrade the runtime binary to match this SDK`,\n    );\n  }\n  throw error;\n}","handlingStrategy":"try-catch","validationCode":"async function runtimeHasFleetApi(client) {\n  const response = await client.fetchImpl(new URL(\"/v1/fleet/runs\", client.baseUrl), {\n    method: \"GET\",\n    headers: { accept: \"application/json\" },\n  });\n  return response.ok || response.status === 405;\n}","typeGuard":"import { RuntimeCapabilityError } from \"@codewhale/runtime-sdk\";\nfunction isRuntimeCapabilityError(error) {\n  return error instanceof RuntimeCapabilityError || error?.name === \"RuntimeCapabilityError\";\n}","tryCatchPattern":"try {\n  await client.startFleetRun(runId);\n} catch (error) {\n  if (isRuntimeCapabilityError(error) && [404, 405, 501].includes(error.status)) {\n    // capability unavailable: upgrade the runtime or disable this code path\n    return handleUnsupportedCapability(error.capability);\n  }\n  throw error;\n}","preventionTips":["Pin the SDK and the runtime binary to the same release so capability endpoints exist on both sides","Probe /v1/fleet/runs once at startup and refuse to submit fleet work when the probe fails","Log error.capability, error.status and error.path whenever this fires to identify the missing endpoint immediately","Keep baseUrl pointed straight at the runtime port (127.0.0.1:7878) unless a proxy is verified to pass /v1/fleet/* through"],"tags":["runtime-api","http","version-skew","sdk","fleet"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}