different-ai/openwork · error

Invalid cloud provider sync status response.

Error message

Invalid cloud provider sync status response.

What it means

parseCloudProviderSyncStatus validates the provider sync status response: it must be an object with a boolean `hasSession` and a `providers` array. Anything else — null, HTML, missing fields, non-array providers — throws this error before per-provider parsing begins.

Source

Thrown at apps/app/src/app/lib/openwork-server.ts:102

    !("sourceProviderId" in value) || typeof value.sourceProviderId !== "string" ||
    !("name" in value) || typeof value.name !== "string" ||
    !("modelIds" in value) || !Array.isArray(value.modelIds) || !value.modelIds.every((item) => typeof item === "string")
  ) return null;
  return {
    cloudProviderId: value.cloudProviderId,
    providerId: value.providerId,
    sourceProviderId: value.sourceProviderId,
    name: value.name,
    source: "source" in value && typeof value.source === "string" ? value.source : null,
    updatedAt: "updatedAt" in value && typeof value.updatedAt === "string" ? value.updatedAt : null,
    modelIds: value.modelIds,
    importedAt: "importedAt" in value && typeof value.importedAt === "number" ? value.importedAt : null,
  };
}

function parseCloudProviderSyncStatus(value: unknown): OpenworkCloudProviderSyncStatus {
  if (!value || typeof value !== "object" || !("hasSession" in value) || typeof value.hasSession !== "boolean" || !("providers" in value) || !Array.isArray(value.providers)) {
    throw new Error("Invalid cloud provider sync status response.");
  }
  const providers: CloudImportedProvider[] = [];
  for (const rawProvider of value.providers) {
    const provider = parseCloudImportedProvider(rawProvider);
    if (!provider) throw new Error("Invalid cloud provider sync provider response.");
    providers.push(provider);
  }
  let lastRun: OpenworkCloudProviderSyncStatus["lastRun"] = null;
  if ("lastRun" in value && value.lastRun !== null) {
    if (!value.lastRun || typeof value.lastRun !== "object" || !("at" in value.lastRun) || (typeof value.lastRun.at !== "string" && typeof value.lastRun.at !== "number")) {
      throw new Error("Invalid cloud provider sync last-run response.");
    }
    const run = parseCloudProviderSyncRun(value.lastRun);
    lastRun = { at: value.lastRun.at, status: run.status, message: run.message };
  }
  // Additive fields (older servers omit them): tolerate absence and malformed
  // entries instead of failing the whole status read.
  const reloadPending = "reloadPending" in value && value.reloadPending === true;

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Log the raw body and HTTP status before parsing to identify the real payload.
  2. Re-authenticate with the Den server; an unauthorized error body often lacks these fields.
  3. Verify the base URL points at the intended OpenWork Den server/environment.
  4. Diff the response against the current server API schema and update the parser if fields changed.

Example fix

// before: parse blindly
const status = parseCloudProviderSyncStatus(await res.json());
// after: guard status + shape, with a descriptive failure
if (!res.ok) throw new Error(`Sync status fetch failed (${res.status}): ${await res.text()}`);
const body = await res.json();
const status = parseCloudProviderSyncStatus(body);
Defensive patterns

Strategy: type-guard

Validate before calling

const body = await res.json();
const looksLikeStatus =
  body && typeof body === "object" &&
  "hasSession" in body && typeof body.hasSession === "boolean" &&
  "providers" in body && Array.isArray(body.providers);
if (!looksLikeStatus) throw new Error(`Sync status payload malformed: ${JSON.stringify(body).slice(0, 200)}`);

Type guard

function isSyncStatusPayload(v: unknown): v is { hasSession: boolean; providers: unknown[] } {
  return (
    typeof v === "object" && v !== null &&
    "hasSession" in v && typeof (v as { hasSession: unknown }).hasSession === "boolean" &&
    "providers" in v && Array.isArray((v as { providers: unknown }).providers)
  );
}

Try / catch

try {
  const status = await client.cloud.providerSync.status();
} catch (err) {
  if (err instanceof Error && err.message.includes("Invalid cloud provider sync status response")) {
    // shape mismatch: verify auth token and environment URL, then log body
    await reauthenticateIfExpired();
  } else throw err;
}

Prevention

When it happens

Trigger: Polling the provider sync status endpoint via createOpenworkServerClient and the body lacks `hasSession` or `providers`, is an error object (e.g. `{error: "unauthorized"}`), or is not JSON at all.

Common situations: Expired/missing auth token returning an error payload with 200, proxy or captive portal injecting HTML, server schema drift renaming fields, hitting the wrong environment (staging/prod mismatch).

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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