← Back to PRs

#12498: fix: guard against incomplete onboarding adapters missing getStatus

by hakityc open 2026-02-09 09:40 View on GitHub →
commands stale
## Summary Fix `TypeError: adapter.getStatus is not a function` during the onboarding wizard (QuickStart flow). ## Problem During `openclaw onboard`, the `CHANNEL_ONBOARDING_ADAPTERS` registry in `src/commands/onboarding/registry.ts` collects `plugin.onboarding` objects from all loaded channel plugins using a simple truthy check: ```typescript plugin.onboarding ? ([plugin.id, plugin.onboarding] as const) : null ``` Some third-party or partially-loaded plugins may expose a truthy `onboarding` object that does not fully conform to the `ChannelOnboardingAdapter` interface — specifically, they may be missing the required `getStatus` method. When `collectChannelStatus()` or `refreshStatus()` later calls `adapter.getStatus(...)`, this causes: ``` TypeError: adapter.getStatus is not a function ``` The crash happens at the "Default model" step during QuickStart onboarding, preventing the wizard from completing. ## Root Cause The registry filter relies solely on a truthy check (`plugin.onboarding ? ...`) to determine if a plugin provides a valid onboarding adapter. However, TypeScript's type system only enforces this at compile time — at runtime, any non-null/undefined value passes the check, even if it doesn't implement the required `getStatus` method. ## Fix Added a runtime type guard in `CHANNEL_ONBOARDING_ADAPTERS` to verify that `plugin.onboarding.getStatus` is actually a function before including the adapter in the registry: ```typescript plugin.onboarding && typeof plugin.onboarding.getStatus === "function" ? ([plugin.id as ChannelChoice, plugin.onboarding] as const) : null ``` This is the minimal, defensive fix — the root filter prevents incomplete adapters from entering the registry at all, so all downstream call sites (`collectChannelStatus`, `refreshStatus`, etc.) are automatically protected. ## Testing - Reproduced the original crash during `openclaw onboard` QuickStart flow - After applying the fix, the onboarding wizard completes successfully - Plugins with valid `onboarding` adapters continue to work as expected ## Files Changed - `src/commands/onboarding/registry.ts` — Added runtime type guard in `CHANNEL_ONBOARDING_ADAPTERS` <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This change hardens the onboarding adapter registry (`src/commands/onboarding/registry.ts`) by adding a runtime guard before registering adapters from channel plugins. Instead of including any truthy `plugin.onboarding`, the registry now only registers onboarding objects that actually implement `getStatus` as a function, preventing `TypeError: adapter.getStatus is not a function` crashes later in the QuickStart flow when status is collected/refreshed. This fits the codebase by keeping the validation at the boundary where third-party plugin objects enter the internal `ChannelOnboardingAdapter` map, so downstream consumers (`getChannelOnboardingAdapter`, `listChannelOnboardingAdapters`, and call sites that invoke `getStatus`) can continue to assume a valid adapter shape. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - The change is narrowly scoped to the onboarding adapter registry and adds a straightforward runtime guard to prevent a known crash when encountering incomplete third-party plugin adapters. It does not alter adapter behavior for valid plugins and does not introduce new control flow outside the registry construction. I was able to fully inspect the modified file; tests could not be executed in this environment due to missing pnpm. - src/commands/onboarding/registry.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs