glanceapp/glance · critical

starting server: %w

Error message

starting server: %w

What it means

Startup error returned when app.server()'s startServer() fails in the watcher-less fallback path. Server startup binds the configured host:port and starts TLS/HTTP serving; failure is dominated by 'address already in use' and permission errors on privileged/unsupported bind addresses.

Source

Thrown at internal/glance/main.go:175

	stopWatching, err := configFilesWatcher(configPath, configContents, configIncludes, onChange, onErr)
	if err == nil {
		defer stopWatching()
	} else {
		log.Printf("Error starting file watcher, config file changes will require a manual restart. (%v)", err)

		config, err := newConfigFromYAML(configContents)
		if err != nil {
			return fmt.Errorf("validating config file: %w", err)
		}

		app, err := newApplication(config)
		if err != nil {
			return fmt.Errorf("creating application: %w", err)
		}

		startServer, _ := app.server()
		if err := startServer(); err != nil {
			return fmt.Errorf("starting server: %w", err)
		}
	}

	<-exitChannel
	return nil
}

func serveUpdateNoticeIfConfigLocationNotMigrated(configPath string) bool {
	if !isRunningInsideDockerContainer() {
		return false
	}

	if _, err := os.Stat(configPath); err == nil {
		return false
	}

	// glance.yml wasn't mounted to begin with or was incorrectly mounted as a directory
	if stat, err := os.Stat("glance.yml"); err != nil || stat.IsDir() {

View on GitHub (pinned to 91324e8de7)

Solutions

  1. Free the port: stop the old instance (`docker stop`, `kill`) or change server.port
  2. If binding <1024, use setcap/PORT env or pick a high port
  3. Confirm the bind host exists on the machine (0.0.0.0 vs a specific IP)
  4. Check TLS file paths/permissions if TLS is enabled

Example fix

# before
server:
  port: 8080   # already in use
# after
server:
  port: 8090
Defensive patterns

Strategy: retry

Validate before calling

// Check port availability before starting
ln, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port))
if err != nil { return fmt.Errorf("port not available: %w", err) }
ln.Close()

Try / catch

Catch 'starting server'; if the wrapped error is EADDRINUSE, wait briefly and retry once after confirming the old process exited; otherwise fail with the bind error.

Prevention

When it happens

Trigger: Another process already listening on server.port; binding to a port <1024 without CAP_NET_BIND_SERVICE; binding to an IP not present on the host; TLS cert/key files unreadable when TLS is configured.

Common situations: Double-starting glance (old container still running); port collision with another service after a config change; Docker port mapping mismatch; systemd unit and manual run racing each other.

Related errors


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