halo-dev/halo · error · TypeError
PluginModule.ucRoutes must be an array.
Error message
PluginModule.ucRoutes must be an array.
What it means
Thrown by preparePluginModule when module.ucRoutes is present but not an array. ucRoutes (user-center routes) must be RouteRecordRaw[] | RouteRecordAppend[], same shape as routes but registered in the user-facing area. A non-array value is rejected with a TypeError before the user-center router is touched.
Source
Thrown at ui/src/setup/setupModules.ts:674
}
function preparePluginModule(
module: PluginModule,
registration: UiProviderRegistration,
report: (
registration: UiProviderRegistration,
stage: UiPluginFailureStage,
error: unknown
) => void
) {
if (module.components && !isRecord(module.components)) {
throw new TypeError("PluginModule.components must be an object.");
}
if (module.routes && !Array.isArray(module.routes)) {
throw new TypeError("PluginModule.routes must be an array.");
}
if (module.ucRoutes && !Array.isArray(module.ucRoutes)) {
throw new TypeError("PluginModule.ucRoutes must be an array.");
}
if (module.formkit && !isRecord(module.formkit)) {
throw new TypeError("PluginModule.formkit must be an object.");
}
if (module.extensionPoints && !isRecord(module.extensionPoints)) {
throw new TypeError("PluginModule.extensionPoints must be an object.");
}
resetRouteMetaAndWrapChunks(module.routes, false, registration, report);
resetRouteMetaAndWrapChunks(module.ucRoutes, false, registration, report);
}
function resetRouteMetaAndWrapChunks(
routes: RouteRecordRaw[] | RouteRecordAppend[] | undefined,
core: boolean,
registration?: UiProviderRegistration,
report?: (
registration: UiProviderRegistration,
stage: UiPluginFailureStage,View on GitHub (pinned to d2f5165f9c)
Solutions
- Return ucRoutes as an array: { ucRoutes: [{ path: '/profile', component: Profile }] }.
- Drop ucRoutes if the plugin adds no user-center routes.
- Typecheck against PluginModule to catch the shape error at build time.
Example fix
// before
export default definePluginModule({ ucRoutes: { name: "profile", path: "/profile", component: Profile } });
// after
export default definePluginModule({ ucRoutes: [{ name: "profile", path: "/profile", component: Profile }] }); Defensive patterns
Strategy: type-guard
Validate before calling
function assertUcRoutesShape(module: { ucRoutes?: unknown }) {
if (module.ucRoutes && !Array.isArray(module.ucRoutes)) {
throw new TypeError("PluginModule.ucRoutes must be an array.");
}
} Type guard
function isRouteArray(value: unknown): value is unknown[] {
return Array.isArray(value);
} Prevention
- Wrap user-center routes in an array literal.
- Typecheck against PluginModule (ucRoutes is typed as the route array union).
- Mirror the routes-array convention for ucRoutes.
When it happens
Trigger: A plugin module returns { ucRoutes: { path: '/profile' } } (object) or a non-array during activation in the user-center app.
Common situations: Author copies the routes shape but forgets the array wrapper for ucRoutes; returns a single user-center route object; mis-merges config.
Related errors
- PluginModule.components must be an object.
- PluginModule.routes must be an array.
- PluginModule.formkit must be an object.
- Required url is missing.
- Invalid type of parameter 'file'.
AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14).
Data as JSON: /api/errors/98cab77ab8f8967a.
Report an issue: GitHub.