different-ai/openwork · error · Error

Failed to connect GitHub repository (${response.status}).

Error message

Failed to connect GitHub repository (${response.status}).

What it means

Thrown by useCreateGithubConnectorInstance in integration-data.tsx when the Den API's POST to create a GitHub connector instance (which links a GitHub repository installation) returns a non-2xx response. The thrown value comes from getRequestError in ee/apps/den-web/app/(den)/_lib/den-flow.ts:527: it returns a ReauthRequiredError for 403 responses whose payload is {error:'reauth'}, otherwise a plain Error whose message is the server's `error`/`message` field, or the fallback "Failed to connect GitHub repository (<status>)." when the payload carries none.

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/integration-data.tsx:629

        "/v1/connectors/github/setup",
        {
          method: "POST",
          body: JSON.stringify({
            branch: input.branch,
            connectorAccountId: input.connectorAccountId,
            connectorInstanceName: input.connectorInstanceName,
            installationId: input.installationId,
            mappings: [],
            ref: `refs/heads/${input.branch}`,
            repositoryFullName: input.repositoryFullName,
            repositoryId: input.repositoryId,
          }),
        },
        20000,
      );

      if (!response.ok) {
        throw getRequestError(payload, response, `Failed to connect GitHub repository (${response.status}).`);
      }

      const item = isRecord(payload) && isRecord(payload.item) ? payload.item : null;
      const connectorInstance = item && isRecord(item.connectorInstance) ? item.connectorInstance : null;
      const connectorTarget = item && isRecord(item.connectorTarget) ? item.connectorTarget : null;
      const connectorInstanceId = connectorInstance ? asString(connectorInstance.id) : null;
      const connectorTargetId = connectorTarget ? asString(connectorTarget.id) : null;
      const repositoryFullName = connectorTarget && isRecord(connectorTarget.targetConfigJson)
        ? asString(connectorTarget.targetConfigJson.repositoryFullName)
        : null;

      if (!connectorInstanceId || !connectorTargetId || !repositoryFullName) {
        throw new Error("GitHub setup response was incomplete.");
      }

        result = {
        connectorInstanceId,
        connectorTargetId,

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Read the actual status code and any server `error` field from the thrown message; handle 403 reauth by routing the user through the sign-in flow (isReauthRequiredError).
  2. If 404/422, verify the GitHub App installation still exists and the user granted repo access, then reconnect from the GitHub install flow.
  3. If 409, list existing connector instances and reuse/connect to the existing instance instead of creating a new one.
  4. If 5xx or network timeout, retry after confirming the Den server is healthy and GitHub status is green.

Example fix

// before
if (!response.ok) {
  throw getRequestError(payload, response, `Failed to connect GitHub repository (${response.status}).`);
}
// after
if (!response.ok) {
  if (isReauthRequiredError(getRequestError(payload, response, ""))) {
    await promptReauth();
  }
  if (response.status === 409) {
    return findExistingConnectorInstance(orgSlug, connectorTargetId);
  }
  throw getRequestError(payload, response, `Failed to connect GitHub repository (${response.status}).`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before calling connectMutation.mutate(...)
if (!githubInstallationId || typeof githubInstallationId !== "string") {
  throw new Error("Select a GitHub App installation before connecting.");
}
if (!navigator.onLine) throw new Error("You appear to be offline.");

Type guard

function isReauthError(e: unknown): e is ReauthRequiredError {
  return e instanceof ReauthRequiredError;
}

Try / catch

try {
  await connectMutation.mutateAsync(input);
} catch (error) {
  if (isReauthError(error)) { startReauth(); return; }
  const status = Number(error.message.match(/\((\d{3})\)/)?.[1] ?? 0);
  if (status === 409) { reuseExistingInstance(); return; }
  showToast(error.message);
}

Prevention

When it happens

Trigger: The mutation posts to the GitHub connector-instance endpoint with a 20s timeout via requestJson; it throws whenever response.ok is false. Typical cases: 401/403 (session expired, missing org scope, or 403+{error:'reauth'} triggering a ReauthRequiredError instead), 404 (connector target or installation no longer exists), 409 (repository/connector instance already connected), 422 (invalid installation id or selected repo), 5xx (Den server or upstream GitHub API failure), or the response arriving after the 20000ms timeout window.

Common situations: User picks a GitHub App installation whose access was revoked; stale Den session token after long idle; the org plan or connector feature flag disallows GitHub connectors; GitHub webhook setup fails server-side producing a 500; user double-clicks connect and hits a duplicate-instance conflict.

Related errors


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