paperclipai/paperclip · error · PaperclipCloudConnectorError

CONNECTOR_BAD_RESPONSE

CONNECTOR_BAD_RESPONSE

Error message

Paperclip Cloud connector returned an invalid instance status

What it means

getInstanceStatus polls the Paperclip Cloud broker's status endpoint and validates the response against a strict mapping: status 'active' requires active===true, 'suspended'/'removed' require active===false. If the broker returns a status/active combination that fits none of the accepted pairs, this error is thrown with CONNECTOR_BAD_RESPONSE.

Source

Thrown at server/src/services/paperclip-cloud-connector.ts:329

    return credentials;
  }

  return {
    async getInstanceStatus(): Promise<"active" | "suspended" | "removed"> {
      let response: ConnectorResponse;
      try {
        response = await call("status", {
          subject: "instance-status",
          companyId: "instance-status",
        });
      } catch (error) {
        if (error instanceof PaperclipCloudConnectorError && error.status === 401) return "removed";
        throw error;
      }
      if (response.status === "active" && response.active === true) return "active";
      if (response.status === "suspended" && response.active === false) return "suspended";
      if (response.status === "removed" && response.active === false) return "removed";
      throw new PaperclipCloudConnectorError("Paperclip Cloud connector returned an invalid instance status", "CONNECTOR_BAD_RESPONSE");
    },
    async getCapabilities(): Promise<PaperclipCloudConnectorProfileId[]> {
      let response: ConnectorResponse;
      try {
        response = await call("status", {
          subject: "instance-capabilities",
          companyId: "instance-capabilities",
        });
      } catch {
        return [];
      }
      if (response.active !== true || response.status !== "active" || !Array.isArray(response.profiles)) return [];
      return [...new Set(response.profiles.flatMap((value) =>
        typeof value === "string" && isPaperclipCloudConnectorProfileId(value) ? [value] : []
      ))];
    },
    async startAuthorization(values: { subject: string; companyId: string; profile?: PaperclipCloudConnectorProfileId; returnUri: string; returnState: string }) {
      const profile = values.profile ?? "gmail.draft";

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check the broker's actual response payload for the instance and confirm status/active values
  2. Upgrade the server package so the client recognizes the broker's new status values
  3. If the broker introduced a new status, add a mapping branch before the throw and coordinate the contract change
  4. Verify no intermediate proxy/CDN is mangling the JSON response

Example fix

// before
const status = await connector.getInstanceStatus(); // throws on unknown broker status

// after
try {
  const status = await connector.getInstanceStatus();
} catch (e) {
  if (e instanceof PaperclipCloudConnectorError && e.code === "CONNECTOR_BAD_RESPONSE") {
    logger.error("broker status payload unrecognized", e);
    // fall back to treating instance as suspended / surface to operator
  } else { throw e; }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-validate the broker payload shape if you call the status endpoint yourself
function isValidInstanceStatus(r: unknown): r is { status: string; active: boolean } {
  return typeof r === "object" && r !== null
    && ["active", "suspended", "removed"].includes((r as any).status)
    && typeof (r as any).active === "boolean";

Type guard

function isKnownInstanceStatus(s: unknown): s is "active" | "suspended" | "removed" {
  return s === "active" || s === "suspended" || s === "removed";

Try / catch

try {
  const status = await connector.getInstanceStatus();
} catch (e) {
  if (isPaperclipCloudConnectorError(e) && e.code === "CONNECTOR_BAD_RESPONSE") {
    // treat instance state as unknown; alert operator instead of acting on it
  } else throw e;
}

Prevention

When it happens

Trigger: The broker's status response contains a status value outside {'active','suspended','removed'}, or an active boolean inconsistent with the status (e.g. status:'active' with active:false, or a missing/mistyped active field).

Common situations: Broker API version drift (new status value like 'degraded' the client doesn't know); a proxy returning an error page parsed loosely; a bug in the broker returning active:null.

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 paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/3100eaf9119c71ae. Report an issue: GitHub.