paperclipai/paperclip · error · Error
${prefix}: "getCommand" must be a function.
Error message
${prefix}: "getCommand" must be a function. What it means
Thrown by assertValidAdapterLoginCapability when loginCapability.getCommand is missing or not a function. getCommand is the required member that returns the fixed, non-secret login command string the server runs in the sandbox; the validator rejects non-function values so a static string command can never slip through.
Source
Thrown at packages/adapter-utils/src/login-capability.ts:136
const cap = value as Record<string, unknown>;
if (!isOneOf(ADAPTER_LOGIN_PANEL_MODES, cap.panelMode)) {
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
- Wrap the command in a zero-argument function: getCommand: () => "mycli login --no-browser".
- Keep the function free of captured secrets; it must return only the fixed command (credentials are captured later via captureCredential).
- Type the capability object as AdapterLoginCapability so a missing getCommand is a compile error.
- Add a load-time test calling validateAdapterLoginCapability on the exported module.
Example fix
// before
loginCapability = { ..., getCommand: "claude login" };
// after
loginCapability = { ..., getCommand: () => "claude login" }; Defensive patterns
Strategy: type-guard
Validate before calling
const ok = typeof (capability as { getCommand?: unknown }).getCommand === "function"; Type guard
import type { AdapterLoginCapability } from "@paperclipai/adapter-utils";
function hasGetCommand(v: unknown): v is AdapterLoginCapability {
return typeof (v as { getCommand?: unknown })?.getCommand === "function";
} Try / catch
try {
assertValidAdapterLoginCapability(cap, "my-adapter");
} catch (error) {
throw new Error(`login capability is malformed: ${String(error)}`);
} Prevention
- getCommand is always () => string, never a bare string.
- Keep the returned command constant and non-secret; secrets are captured by captureCredential later.
- Let TypeScript check the whole capability object against AdapterLoginCapability before export.
When it happens
Trigger: An adapter declares loginCapability = { getCommand: "paperclip login", ... } (the raw string instead of a function) or omits getCommand while declaring the rest of the capability; the loader's validateAdapterLoginCapability throws before registration completes.
Common situations: Authors storing the command directly as a string because it is constant; partial capability objects written for documentation; refactors that move command construction elsewhere and leave the field dangling.
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
- ${prefix}: "panelMode" must be one of ${ADAPTER_LOGIN_PANEL_
- ${prefix}: "sandboxTransport" must be one of ${ADAPTER_LOGIN
- ${prefix}: "timeoutPolicy" must be one of ${ADAPTER_LOGIN_TI
- ${prefix}: "parsePrompt" must be a function.
- ${prefix}: "captureCredential" must be a function when prese
AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-21).
Data as JSON: /api/errors/a6db4a913e9afbee.
Report an issue: GitHub.