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

  1. Return ucRoutes as an array: { ucRoutes: [{ path: '/profile', component: Profile }] }.
  2. Drop ucRoutes if the plugin adds no user-center routes.
  3. 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

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


AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14). Data as JSON: /api/errors/98cab77ab8f8967a. Report an issue: GitHub.