different-ai/openwork · error

OAuth issuer review response was incomplete.

Error message

OAuth issuer review response was incomplete.

What it means

The OAuth issuer review mutation calls runReauthableAction (confirm) or request() directly (other actions) and stores the result in `review`. If neither path assigns a value — e.g. the wrapper resolved without executing the request — this guard throws. It prevents the mutation from resolving with an undefined review record.

Source

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

          `/v1/mcp-connections/${encodeURIComponent(connectionId)}/oauth/issuer-review`,
          {
            method: "POST",
            headers: getOrgScopeHeaders(requireOrgId(orgId)),
            body: JSON.stringify(body),
          },
          30000,
        );
        if (!response.ok) {
          throw getRequestError(payload, response, `Failed to review the OAuth issuer (${response.status}).`);
        }
        review = payload as McpIssuerReview;
      };
      if (input.action === "confirm") {
        await runReauthableAction("review-mcp-oauth-issuer", request);
      } else {
        await request();
      }
      if (!review) throw new Error("OAuth issuer review response was incomplete.");
      return review;
    },
    onSuccess: (_review, input) => {
      if (input.action === "confirm") {
        queryClient.invalidateQueries({ queryKey: mcpConnectionQueryKeys.all });
      }
    },
  });
}

export function useReplaceMcpConnectionAccess() {
  const queryClient = useQueryClient();
  const { orgId, runReauthableAction } = useOrgDashboard();

  return useMutation({
    mutationFn: async (input: { connectionId: string; access: McpConnectionAccessInput }): Promise<string> => {
      let result: string | null = null;
      await runReauthableAction("replace-mcp-connection-access", async () => {

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Confirm runReauthableAction returns the callback's value after re-auth and doesn't resolve undefined when re-auth is dismissed
  2. Log inside `request` to verify the fetch runs and assigns `review`
  3. Handle the dismissed-reauth case in UI (catch and surface 'review not completed' instead of a raw error)
  4. Check the review endpoint returns the review object with 2xx

Example fix

// before
if (!review) throw new Error("OAuth issuer review response was incomplete.");
// after
if (!review) {
  throw new Error(`OAuth issuer review (${input.action}) returned no result; re-auth may have been dismissed.`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

const canReview = typeof issuerId === 'string' && ['confirm','reject'].includes(action);

Type guard

function isOAuthIssuerReview(v: unknown): v is OAuthIssuerReview {
  return isRecord(v) && typeof (v as Record<string, unknown>).issuerId === 'string';
}

Try / catch

try {
  await reviewIssuer.mutateAsync({ action, issuerId });
} catch (e) {
  if (isReauthDismissedError(e)) { promptSignIn(); return; }
  showToast({ variant: 'error', title: 'OAuth issuer review failed', description: e instanceof Error ? e.message : String(e) });
}

Prevention

When it happens

Trigger: mutateAsync({action:'confirm'|'reject', ...}) where runReauthableAction('review-mcp-oauth-issuer', request) resolves without invoking `request` (re-auth cancelled/skipped) or `request()` itself resolves without populating `review`.

Common situations: Expired Den session during an OAuth issuer security review; user re-auth flow was dismissed by the wrapper; a change to runReauthableAction changed its return contract.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


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