glanceapp/glance · error

page slug "%s" is reserved

Error message

page slug "%s" is reserved

What it means

Startup fails when a page's slug collides with one of glance's reserved slugs ("login" or "logout"). Slugs derive from the page title via titleToSlug when not explicitly set, so a page literally titled or slugged 'Login' or 'Logout' would shadow the auth endpoints and is rejected.

Source

Thrown at internal/glance/glance.go:162

	// Init pages
	//

	app.slugToPage[""] = &config.Pages[0]

	providers := &widgetProviders{
		assetResolver: app.StaticAssetPath,
	}

	for p := range config.Pages {
		page := &config.Pages[p]
		page.PrimaryColumnIndex = -1

		if page.Slug == "" {
			page.Slug = titleToSlug(page.Title)
		}

		if slices.Contains(reservedPageSlugs, page.Slug) {
			return nil, fmt.Errorf("page slug \"%s\" is reserved", page.Slug)
		}

		app.slugToPage[page.Slug] = page

		if page.Width == "default" {
			page.Width = ""
		}

		if page.DesktopNavigationWidth == "" && page.DesktopNavigationWidth != "default" {
			page.DesktopNavigationWidth = page.Width
		}

		for i := range page.HeadWidgets {
			widget := page.HeadWidgets[i]
			app.widgetByID[widget.GetID()] = widget
			widget.setProviders(providers)
		}

View on GitHub (pinned to 91324e8de7)

Solutions

  1. Rename the page title or set an explicit non-reserved slug (e.g. `sign-in`)
  2. If you want a login-adjacent page, link to the real /login route instead of creating a page
  3. Check all pages' derived slugs: the slug is the lowercased, hyphenated title, so 'LOGOUT' and 'Log Out' both collide

Example fix

# before
pages:
  - title: Login
# after
pages:
  - title: Sign In
    slug: sign-in
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check page slugs against the reserved set
reserved := map[string]bool{"login": true, "logout": true}
for _, p := range cfg.Pages {
    slug := p.Slug
    if slug == "" { slug = titleToSlug(p.Title) }
    if reserved[slug] { return fmt.Errorf("page %q collides with reserved slug %q", p.Title, slug) }
}

Type guard

func isReservedPageSlug(slug string) bool { return slug == "login" || slug == "logout" }

Try / catch

Catch at startup and rename the offending page; the message already includes the colliding slug — no dynamic recovery exists.

Prevention

When it happens

Trigger: Declaring `pages: - title: Login` or `- slug: login` (case variants included, since titleToSlug lowercases) while any page exists with that derived or explicit slug. Note the first page also gets registered under "" earlier, but the check only guards the reserved list.

Common situations: Adding an SSO/status page named 'Login' or 'Logout'; migrating a dashboard whose page titles happen to include reserved words; explicitly setting slug: logout for a session-info page.

Related errors


AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15). Data as JSON: /api/errors/cd89000920bedea4. Report an issue: GitHub.