different-ai/openwork · error

Native provider client response was incomplete.

Error message

Native provider client response was incomplete.

What it means

parseNativeProviderClient validates the shape of the native-provider OAuth client payload before use. When the response is not a JSON object at all (null, array, string, empty body), it throws this error immediately. The sibling check at line 1013 covers individual field type mismatches.

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/mcp-connections-data.tsx:1001

  clientId?: string;
  clientSecret?: string;
  tenantId?: string;
  features: string[];
};

export type NativeProviderClient = {
  providerId: string;
  configured: boolean;
  clientId: string | null;
  tenantId: string | null;
  features: string[];
  scopes: string[];
  redirectUri: string;
};

function parseNativeProviderClient(payload: unknown): NativeProviderClient {
  if (!isRecord(payload)) {
    throw new Error("Native provider client response was incomplete.");
  }
  const { providerId, configured, clientId, tenantId, features, scopes, redirectUri } = payload;
  if (
    typeof providerId !== "string"
    || typeof configured !== "boolean"
    || (typeof clientId !== "string" && clientId !== null)
    || (typeof tenantId !== "string" && tenantId !== null)
    || !isStringArray(features)
    || !isStringArray(scopes)
    || typeof redirectUri !== "string"
  ) {
    throw new Error("Native provider client response was incomplete.");
  }
  return { providerId, configured, clientId, tenantId, features, scopes, redirectUri };
}

/**
 * Native providers are configured with an org OAuth

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Log the raw payload before parseNativeProviderClient to see what the server actually returned
  2. Check the fetch URL/route — an HTML 200 body usually means a redirect to a login page or SPA fallback
  3. Verify the endpoint serializes a JSON object on success (not 204/empty)
  4. Confirm authentication cookies/tokens are sent so the gateway doesn't substitute its own 200 response

Example fix

// before
if (!isRecord(payload)) {
  throw new Error("Native provider client response was incomplete.");
}
// after
if (!isRecord(payload)) {
  throw new Error(`Native provider client response was not an object: ${JSON.stringify(payload).slice(0, 200)}`);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const res = await fetch(url, { credentials: 'include' });
const ct = res.headers.get('content-type') ?? '';
if (!ct.includes('application/json')) throw new Error(`expected JSON, got ${ct}`);
const payload = await res.json();

Type guard

function isRecord(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

try {
  const client = await fetchNativeProviderClient(providerId);
} catch (e) {
  showToast({ variant: 'error', title: 'Could not load OAuth client', description: e instanceof Error ? e.message : String(e) });
}

Prevention

When it happens

Trigger: GET the native provider client endpoint returns 2xx with a non-object body: empty response, HTML error page behind a proxy, JSON array, or `null` literal.

Common situations: Reverse proxy/auth gateway returned an HTML login page with 200; server route returns 204/empty; misrouted request hit a non-API path; content-type confusion causing parsed payload to be a string.

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/1dec7e186f995fd2. Report an issue: GitHub.