{"record":{"id":"241eff7faae2016b","repo":"halo-dev/halo","slug":"pluginmodule-formkit-must-be-an-object","errorCode":null,"errorMessage":"PluginModule.formkit must be an object.","messagePattern":"PluginModule\\.formkit must be an object\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ui/src/setup/setupModules.ts","lineNumber":677,"sourceCode":"  module: PluginModule,\n  registration: UiProviderRegistration,\n  report: (\n    registration: UiProviderRegistration,\n    stage: UiPluginFailureStage,\n    error: unknown\n  ) => void\n) {\n  if (module.components && !isRecord(module.components)) {\n    throw new TypeError(\"PluginModule.components must be an object.\");\n  }\n  if (module.routes && !Array.isArray(module.routes)) {\n    throw new TypeError(\"PluginModule.routes must be an array.\");\n  }\n  if (module.ucRoutes && !Array.isArray(module.ucRoutes)) {\n    throw new TypeError(\"PluginModule.ucRoutes must be an array.\");\n  }\n  if (module.formkit && !isRecord(module.formkit)) {\n    throw new TypeError(\"PluginModule.formkit must be an object.\");\n  }\n  if (module.extensionPoints && !isRecord(module.extensionPoints)) {\n    throw new TypeError(\"PluginModule.extensionPoints must be an object.\");\n  }\n  resetRouteMetaAndWrapChunks(module.routes, false, registration, report);\n  resetRouteMetaAndWrapChunks(module.ucRoutes, false, registration, report);\n}\n\nfunction resetRouteMetaAndWrapChunks(\n  routes: RouteRecordRaw[] | RouteRecordAppend[] | undefined,\n  core: boolean,\n  registration?: UiProviderRegistration,\n  report?: (\n    registration: UiProviderRegistration,\n    stage: UiPluginFailureStage,\n    error: unknown\n  ) => void\n) {","sourceCodeStart":659,"sourceCodeEnd":695,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/ui/src/setup/setupModules.ts#L659-L695","documentation":"Thrown by preparePluginModule when module.formkit is present but not a plain object (isRecord fails — array, primitive, function, null). formkit must be a PluginFormKit record mapping input names to FormKit definitions so Halo can register custom FormKit inputs. A wrong shape would corrupt FormKit config, so activation throws a TypeError.","triggerScenarios":"A plugin module returns { formkit: [...] } (array) or { formkit: null } or a function during activation; preparePluginModule's isRecord(module.formkit) check fails.","commonSituations":"Author mistakes formkit for an array of definitions; assigns a single schema; a generator returns the wrong shape.","solutions":["Return formkit as an object keyed by input name: { formkit: { myInput: { type: 'input' } } }.","Omit the field if the plugin ships no custom FormKit inputs.","Typecheck the plugin module against PluginModule."],"exampleFix":"// before\nexport default definePluginModule({ formkit: [{ type: \"input\", name: \"myInput\" }] });\n\n// after\nexport default definePluginModule({ formkit: { myInput: { type: \"input\" } } });","handlingStrategy":"type-guard","validationCode":"function assertFormkitShape(module: { formkit?: unknown }) {\n  if (module.formkit && (typeof module.formkit !== \"object\" || module.formkit === null || Array.isArray(module.formkit))) {\n    throw new TypeError(\"PluginModule.formkit must be an object.\");\n  }\n}","typeGuard":"function isFormkitRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}","tryCatchPattern":null,"preventionTips":["Return formkit as an object keyed by input name.","Typecheck the plugin module with vue-tsc.","Omit formkit when the plugin ships no custom inputs."],"tags":["runtime","plugin-module","formkit","validation","console"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}