different-ai/openwork · error · Error

Connection details were missing from the worker response.

Error message

Connection details were missing from the worker response.

What it means

After a successful (2xx) connection-details response, loadConnectionDetails extracts worker tokens via getWorkerTokens(payload). If the payload does not contain the expected openworkUrl/ownerToken/clientToken structure, this error is thrown because the UI cannot connect to the worker without these credentials. It indicates a 2xx response missing required fields.

Solutions

  1. Inspect the raw response body and compare with getWorkerTokens' expected fields (openworkUrl, ownerToken, clientToken).
  2. Retry after provisioning completes — partial 200s are often transient.
  3. Update getWorkerTokens if the server renamed/moved fields into an envelope.
  4. Verify server and client versions are aligned; redeploy the stale side.

Example fix

// before
const tokens = getWorkerTokens(payload);
if (!tokens) throw new Error("Connection details were missing from the worker response.");
// after
const tokens = getWorkerTokens(payload?.worker ?? payload?.data ?? payload);
if (!tokens) throw new Error("Connection details were missing from the worker response.");
Defensive patterns

Strategy: type-guard

Validate before calling

const tokens = getWorkerTokens(payload);
if (!tokens || !tokens.openworkUrl || !tokens.ownerToken || !tokens.clientToken) {
  // retry or show provisioning-in-progress state
}

Type guard

function isWorkerTokens(v: unknown): v is { openworkUrl: string; ownerToken: string; clientToken: string } {
  const t = v as Record<string, unknown> | null;
  return !!t && typeof t.openworkUrl === "string" &&
    typeof t.ownerToken === "string" && t.ownerToken.length > 0 &&
    typeof t.clientToken === "string" && t.clientToken.length > 0;
}

Try / catch

try {
  await loadConnectionDetails();
} catch (err) {
  if (err instanceof Error && err.message.includes("missing from the worker response")) {
    showToast("Sandbox is still provisioning — retrying…");
    setTimeout(loadConnectionDetails, 5000);
  } else throw err;
}

Prevention

When it happens

Trigger: The endpoint returns 200 but omits tokens (worker not fully provisioned), uses a different envelope, or omits the expiring OpenWork URL despite includeExpiringOpenworkUrl:true; proxies stripping fields.

Common situations: Sandbox mid-provisioning returns partial data; server version predates the expiring-URL feature; security hardening redacting owner/client tokens; client/server contract skew.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/c313d219a0b64d73. Report an issue: GitHub.

Appendix: source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/background-agents-screen.tsx:328

    try {
      const { response, payload } = await requestJson(
        `/v1/workers/${encodeURIComponent(workerId)}/tokens`,
        {
          method: "POST",
          body: JSON.stringify({ includeExpiringOpenworkUrl: true }),
        },
        12000,
      );

      if (!response.ok) {
        throw new Error(
          getErrorMessage(payload, `Failed to load connection details (${response.status}).`),
        );
      }

      const tokens = getWorkerTokens(payload);
      if (!tokens) {
        throw new Error("Connection details were missing from the worker response.");
      }

      const nextDetails: ConnectionDetails = {
        openworkUrl: tokens.openworkUrl,
        ownerToken: tokens.ownerToken,
        clientToken: tokens.clientToken,
        openworkAppConnectUrl: buildOpenworkAppConnectUrl(
          runtimeConfig.openworkAppConnectUrl,
          tokens.previewOpenworkUrl,
          tokens.clientToken,
          workerId,
          workerName,
          { autoConnect: true },
        ),
        openworkDeepLink: buildOpenworkDeepLink(
          tokens.openworkUrl,
          tokens.hostToken ?? tokens.ownerToken,
          workerId,

View on GitHub (pinned to 2b7df46e8a)