{"record":{"id":"91f3227bd8b157e5","repo":"paperclipai/paperclip","slug":"prefix-timeoutpolicy-must-be-one-of-adapte","errorCode":null,"errorMessage":"${prefix}: \"timeoutPolicy\" must be one of ${ADAPTER_LOGIN_TIMEOUT_POLICIES.join(\", \")}.","messagePattern":"(.+?): \"timeoutPolicy\" must be one of (.+?)\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/adapter-utils/src/login-capability.ts","lineNumber":131,"sourceCode":"): asserts value is AdapterLoginCapability {\n  const prefix = `Adapter \"${adapterType}\" declares an invalid login capability`;\n  if (typeof value !== \"object\" || value === null) {\n    throw new Error(`${prefix}: the capability must be an object.`);\n  }\n  const cap = value as Record<string, unknown>;\n\n  if (!isOneOf(ADAPTER_LOGIN_PANEL_MODES, cap.panelMode)) {\n    throw new Error(\n      `${prefix}: \"panelMode\" must be one of ${ADAPTER_LOGIN_PANEL_MODES.join(\", \")}.`,\n    );\n  }\n  if (!isOneOf(ADAPTER_LOGIN_SANDBOX_TRANSPORTS, cap.sandboxTransport)) {\n    throw new Error(\n      `${prefix}: \"sandboxTransport\" must be one of ${ADAPTER_LOGIN_SANDBOX_TRANSPORTS.join(\", \")}.`,\n    );\n  }\n  if (!isOneOf(ADAPTER_LOGIN_TIMEOUT_POLICIES, cap.timeoutPolicy)) {\n    throw new Error(\n      `${prefix}: \"timeoutPolicy\" must be one of ${ADAPTER_LOGIN_TIMEOUT_POLICIES.join(\", \")}.`,\n    );\n  }\n  if (typeof cap.getCommand !== \"function\") {\n    throw new Error(`${prefix}: \"getCommand\" must be a function.`);\n  }\n  if (typeof cap.parsePrompt !== \"function\") {\n    throw new Error(`${prefix}: \"parsePrompt\" must be a function.`);\n  }\n  if (cap.captureCredential !== undefined && typeof cap.captureCredential !== \"function\") {\n    throw new Error(`${prefix}: \"captureCredential\" must be a function when present.`);\n  }\n  if (cap.onComplete !== undefined && typeof cap.onComplete !== \"function\") {\n    throw new Error(`${prefix}: \"onComplete\" must be a function when present.`);\n  }\n  if (\n    cap.completionClaim !== undefined &&\n    !isOneOf(ADAPTER_LOGIN_COMPLETION_CLAIMS, cap.completionClaim)","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/packages/adapter-utils/src/login-capability.ts#L113-L149","documentation":"Thrown by assertValidAdapterLoginCapability when loginCapability.timeoutPolicy is not \"caller_bounded\" or \"fixed\". The policy decides who owns the login timeout: caller_bounded lets the caller pass a deadline, fixed binds the login to one adapter-defined timeout.","triggerScenarios":"An adapter exports loginCapability with timeoutPolicy missing, spelled differently (\"caller-bounded\", \"adaptive\"), or set to null; validateAdapterLoginCapability runs at load time and rejects the module.","commonSituations":"Copy-pasting a capability template and leaving placeholders; kebab-case vs snake_case confusion; constructing capabilities from user/config input where the string is never type-checked.","solutions":["Set timeoutPolicy to \"caller_bounded\" (caller supplies the deadline) or \"fixed\" (the adapter's fixed timeout applies).","Type the field as AdapterLoginTimeoutPolicy for compile-time enforcement.","Run validateAdapterLoginCapability(module) in the adapter's test suite.","Check adapter-utils version alignment if the value looks valid but still fails."],"exampleFix":"// before\nloginCapability = { timeoutPolicy: \"caller-bounded\", ... };\n\n// after\nloginCapability = { timeoutPolicy: \"caller_bounded\" as const, ... };","handlingStrategy":"type-guard","validationCode":"import { ADAPTER_LOGIN_TIMEOUT_POLICIES } from \"@paperclipai/adapter-utils\";\n\nconst ok = (ADAPTER_LOGIN_TIMEOUT_POLICIES as readonly string[]).includes(capability.timeoutPolicy);","typeGuard":"import { ADAPTER_LOGIN_TIMEOUT_POLICIES, type AdapterLoginCapability } from \"@paperclipai/adapter-utils\";\n\nfunction hasValidTimeoutPolicy(v: unknown): v is AdapterLoginCapability {\n  const c = v as Record<string, unknown>;\n  return (ADAPTER_LOGIN_TIMEOUT_POLICIES as readonly string[]).includes(c?.timeoutPolicy as string);\n}","tryCatchPattern":"try {\n  validateAdapterLoginCapability(mod);\n} catch (error) {\n  throw new Error(`adapter ${mod.type} cannot be registered: ${String(error)}`);\n}","preventionTips":["Use the exact snake_case spellings caller_bounded / fixed.","Type the field as AdapterLoginTimeoutPolicy.","Keep capability fixtures in one place so all adapters share verified values."],"tags":["adapter","login-capability","validation","timeout","typescript"],"backgroundTag":"invalid-enum-value","analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-21T17:58:32.592Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}