BloopAI/vibe-kanban · error · Error
Selected profile key not found
Error message
Selected profile key not found
What it means
handleApplyMcpServers throws 'Selected profile key not found' when the profiles record contains no value reference-equal to the selectedProfile being saved. The key is required as the `executor` argument for machineClient.saveMcpServers. Same root cause as the load path: the selected ExecutorProfile object is not from the current profiles map.
Source
Thrown at packages/web-core/src/shared/dialogs/settings/settings/McpSettingsSection.tsx:156
try {
if (mcpServers.trim()) {
try {
const fullConfig = JSON.parse(mcpServers);
McpConfigStrategyGeneral.validateFullConfig(mcpConfig, fullConfig);
const mcpServersConfig =
McpConfigStrategyGeneral.extractServersForApi(
mcpConfig,
fullConfig
);
const selectedProfileKey = profiles
? Object.keys(profiles).find(
(key) => profiles[key] === selectedProfile
)
: null;
if (!selectedProfileKey) {
throw new Error('Selected profile key not found');
}
if (!machineClient) {
throw new Error('Machine client is required');
}
await machineClient.saveMcpServers(
{
executor: selectedProfileKey as BaseCodingAgent,
},
{ servers: mcpServersConfig }
);
setOriginalMcpServers(mcpServers);
setSuccess(true);
setTimeout(() => setSuccess(false), 3000);
} catch (mcpErr) {
if (mcpErr instanceof SyntaxError) {View on GitHub (pinned to 4deb7eca8f)
Solutions
- Reopen the settings page so selectedProfile rebinds to the current profiles map, then save again
- Keep the selected executor's string key in component state and use it directly for saveMcpServers instead of reverse-looking-up by object identity
- Check the executor still exists in config; restore/rename it in the config file if removed
- Serialize the save behind a check that profiles is loaded and contains selectedProfile
Example fix
// before
const selectedProfileKey = Object.keys(profiles).find((key) => profiles[key] === selectedProfile);
// after (store key when selecting)
const [selectedKey, setSelectedKey] = useState<string | null>(null);
// use selectedKey directly: saveMcpServers({ executor: selectedKey as BaseCodingAgent }, ...) Defensive patterns
Strategy: validation
Validate before calling
// before saving:
if (!profiles || !selectedProfileKey) {
setMcpError('Agent selection is stale — reselect the agent and save again.');
return;
}
await machineClient.saveMcpServers({ executor: selectedProfileKey as BaseCodingAgent }, { servers: mcpServersConfig }); Type guard
function hasSelectedProfileKey(profiles: Record<string, ExecutorProfile> | null, key: string | null): key is string {
return !!key && !!profiles && key in profiles;
} Try / catch
try {
const key = findProfileKey(profiles, selectedProfile); // by reference
if (!key) { setMcpError('Selected agent no longer exists — reselect and retry.'); return; }
await machineClient.saveMcpServers({ executor: key as BaseCodingAgent }, { servers: mcpServersConfig });
setSuccess(true);
} catch (err) {
setMcpError(err instanceof Error ? err.message : t('settings.mcp.errors.saveFailed'));
} Prevention
- Persist the executor key (string) in state when the user picks an agent, and save with that key
- Revalidate the key exists in profiles before enabling Save
- Rebind selectedProfile whenever the profiles record changes
- Block saving while profiles is null or still loading
When it happens
Trigger: User clicks Save (SettingsSaveBar onSave) after profiles were reloaded/replaced (or is null) so Object.keys(profiles).find(key => profiles[key] === selectedProfile) returns undefined.
Common situations: User System config refetched in background while editing MCP JSON, replacing profile objects; selected executor removed from config before saving; saving immediately after page load before profiles finished hydrating.
Related errors
- Profile key not found
- Machine client is required
- Machine client is required
- Action "${action.id}" requires a workspace target
- Skipping retry image upload: missing session id for attempt
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/05613a355ac42867.
Report an issue: GitHub.