paperclipai/paperclip · error · Error

${prefix}: "parsePrompt" must be a function.

Error message

${prefix}: "parsePrompt" must be a function.

What it means

Thrown by assertValidAdapterLoginCapability when loginCapability.parsePrompt is missing or not a function. parsePrompt(output: string) => AdapterLoginPrompt | null is required: the server feeds it incremental login output and it must return the authorization URL (and code) once a prompt appears, or null while waiting. A missing parser means the login flow could never surface the URL to the user.

Source

Thrown at packages/adapter-utils/src/login-capability.ts:139

    throw new Error(
      `${prefix}: "panelMode" must be one of ${ADAPTER_LOGIN_PANEL_MODES.join(", ")}.`,
    );
  }
  if (!isOneOf(ADAPTER_LOGIN_SANDBOX_TRANSPORTS, cap.sandboxTransport)) {
    throw new Error(
      `${prefix}: "sandboxTransport" must be one of ${ADAPTER_LOGIN_SANDBOX_TRANSPORTS.join(", ")}.`,
    );
  }
  if (!isOneOf(ADAPTER_LOGIN_TIMEOUT_POLICIES, cap.timeoutPolicy)) {
    throw new Error(
      `${prefix}: "timeoutPolicy" must be one of ${ADAPTER_LOGIN_TIMEOUT_POLICIES.join(", ")}.`,
    );
  }
  if (typeof cap.getCommand !== "function") {
    throw new Error(`${prefix}: "getCommand" must be a function.`);
  }
  if (typeof cap.parsePrompt !== "function") {
    throw new Error(`${prefix}: "parsePrompt" must be a function.`);
  }
  if (cap.captureCredential !== undefined && typeof cap.captureCredential !== "function") {
    throw new Error(`${prefix}: "captureCredential" must be a function when present.`);
  }
  if (cap.onComplete !== undefined && typeof cap.onComplete !== "function") {
    throw new Error(`${prefix}: "onComplete" must be a function when present.`);
  }
  if (
    cap.completionClaim !== undefined &&
    !isOneOf(ADAPTER_LOGIN_COMPLETION_CLAIMS, cap.completionClaim)
  ) {
    throw new Error(
      `${prefix}: "completionClaim" must be one of ${ADAPTER_LOGIN_COMPLETION_CLAIMS.join(", ")} when present.`,
    );
  }
}

/**

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Implement parsePrompt as a function returning { url } (plus optional code) when the output contains a prompt, else null.
  2. Keep every input byte out of the returned prompt and out of thrown errors (the contract forbids echoing sandbox output).
  3. Type the capability as AdapterLoginCapability so the missing member fails to compile.
  4. Test parsePrompt against a recorded login-output fixture in the adapter package.

Example fix

// before
loginCapability = { ..., getCommand: () => "claude login" };

// after
loginCapability = {
  ...,
  parsePrompt: (output) => {
    const m = output.match(/https:\/\/example\.com\/auth\?code=\S+/);
    return m ? { url: m[0] } : null;
  },
};
Defensive patterns

Strategy: type-guard

Validate before calling

const ok = typeof (capability as { parsePrompt?: unknown }).parsePrompt === "function";

Type guard

import type { AdapterLoginCapability } from "@paperclipai/adapter-utils";

function hasParsePrompt(v: unknown): v is AdapterLoginCapability {
  return typeof (v as { parsePrompt?: unknown })?.parsePrompt === "function";
}

Try / catch

try {
  assertValidAdapterLoginCapability(cap, adapterType);
} catch (error) {
  failAdapterLoad(error); // never register a capability without a prompt parser
}

Prevention

When it happens

Trigger: An adapter declares a loginCapability with getCommand but no parsePrompt; or sets parsePrompt to an object/regex instead of a function; validateAdapterLoginCapability rejects it at load.

Common situations: Adapters that only need to run a command and forget the server must extract the auth URL from output; parse logic kept as data (a regex pattern string) instead of wrapped in a function; partial implementations shipped by mistake.

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 paperclipai/paperclip@a7e689b3c3 (2026-08-21). Data as JSON: /api/errors/5a7f3bbac7f8c186. Report an issue: GitHub.