mihomo-party-org/clash-party · error · Error
Missing profile import handler
Error message
Missing profile import handler
What it means
The profile edit-info modal's onSave() branches on import vs edit mode. In import mode it requires the addProfileItem function (typically from a context/hook); if that value is undefined it throws 'Missing profile import handler' instead of calling it. This guard turns an invisible wiring bug (missing provider or prop) into an explicit error.
Source
Thrown at src/renderer/src/components/profiles/edit-info-modal.tsx:63
...item
})
const inputWidth = 'w-[400px] md:w-[400px] lg:w-[600px] xl:w-[800px]'
const { t } = useTranslation()
const isImportMode = mode === 'import'
const canSave =
!isImportMode || (values.type === 'remote' ? Boolean(values.url?.trim()) : values.file != null)
const onSave = async (): Promise<void> => {
try {
const updatedItem = {
...values,
override: values.override?.filter(
(i) =>
overrideItems.find((t) => t.id === i) && !overrideItems.find((t) => t.id === i)?.global
)
}
if (isImportMode) {
if (!addProfileItem) throw new Error('Missing profile import handler')
await addProfileItem(updatedItem)
} else {
if (!updateProfileItem) throw new Error('Missing profile update handler')
await updateProfileItem(updatedItem)
await addProfileUpdater(updatedItem)
await mihomoHotReloadConfig()
}
onClose()
} catch (e) {
toast.error(String(e))
}
}
const selectLocalFile = async (): Promise<void> => {
const files = await getFilePath(['yml', 'yaml'])
if (!files?.length) return
const file = await readTextFile(files[0])View on GitHub (pinned to 911e090537)
Solutions
- Render the modal inside the component tree that provides addProfileItem (inside the profiles context provider).
- Check where addProfileItem comes from (useContext/useHook) and confirm the provider wraps the modal's mount point.
- Pass the handler explicitly as a prop if context scoping is awkward.
- Verify the provider's value object actually includes addProfileItem (not omitted during destructuring).
Example fix
// before
if (isImportMode) {
if (!addProfileItem) throw new Error('Missing profile import handler')
// after
// in the component that owns the modal:
const { addProfileItem } = useProfiles() // ensure called inside <ProfilesProvider>
if (isImportMode && addProfileItem) {
await addProfileItem(updatedItem)
} Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof addProfileItem !== 'function') {
console.error('edit-info-modal rendered outside ProfilesProvider or provider value incomplete')
return
} Type guard
function hasImportHandler(h: unknown): h is (item: ProfileItem) => Promise<void> {
return typeof h === 'function'
} Try / catch
try {
if (isImportMode && typeof addProfileItem === 'function') {
await addProfileItem(updatedItem)
} else if (!isImportMode && typeof updateProfileItem === 'function') {
await updateProfileItem(updatedItem)
}
onClose()
} catch (e) {
notify.error(String(e))
} Prevention
- Render modals inside the provider subtree, not via root portals that escape it.
- Destructure context handlers through typed hooks so missing fields surface at typecheck.
- Add a dev-mode assertion that context handlers are functions when the modal mounts.
- Cover add-profile flow in component tests with the real provider.
When it happens
Trigger: Opening the edit-info modal to ADD a profile while the component rendering it is outside the provider that supplies addProfileItem (e.g. modal hoisted above the profiles context, or the context hook returning undefined handlers).
Common situations: Refactoring modal to render at the root via portal outside <ProfilesProvider>; a context consumer whose value omits addProfileItem; conditional provider mounting (provider not yet mounted when modal submits).
Related errors
- Missing profile update handler
- useConfig must be used within Provider
- useAppConfig must be used within an AppConfigProvider
- useControledMihomoConfig must be used within a ControledMiho
- useGroups must be used within an GroupsProvider
AI-assisted analysis of mihomo-party-org/clash-party@911e090537 (2026-08-30).
Data as JSON: /api/errors/be1a9e96a7d1722c.
Report an issue: GitHub.