amir20/dozzle · error

failed to create agent server

Error message

failed to create agent server: %w

What it means

Returned by AgentCmd.Run when agent.NewServer fails to construct the gRPC agent server. The server wraps the shared client service, TLS certificates, and notification handler; failure usually indicates the supplied TLS credentials are invalid for gRPC use.

Solutions

  1. Regenerate certificates with `make generate` so cert/key match and are valid.
  2. Drop custom --cert-path/--key-path overrides to use the embedded certs.
  3. Validate the PEM pair: `openssl x509 -in cert.pem -noout` and `openssl rsa -in key.pem -check`.
  4. Confirm agent and main server use the same shared key/cert.
  5. Update dozzle to the latest release.

Example fix

// before
--cert-path /etc/dozzle/cert.pem --key-path /etc/dozzle/mismatched.key
// after
--cert-path /etc/dozzle/cert.pem --key-path /etc/dozzle/key.pem  # matching pair
// or regenerate:
make generate
Defensive patterns

Strategy: validation

Validate before calling

openssl x509 -in cert.pem -noout && openssl rsa -in key.pem -check && diff <(openssl x509 -in cert.pem -noout -modulus) <(openssl rsa -in key.pem -noout -modulus) && echo 'cert/key pair OK'

Try / catch

if err := agentCmd.Run(args, embeddedCerts); err != nil {
  if strings.Contains(err.Error(), "failed to create agent server") {
    log.Fatal().Err(err).Msg("invalid TLS material for gRPC server; regenerate certs")
  }
}

Prevention

When it happens

Trigger: certs parsed from ReadCertificates are structurally invalid for gRPC credentials (malformed cert/key pair); passing nil or mismatched certificate material to NewServer.

Common situations: Custom cert/key files that load as PEM but fail gRPC credential construction; certs regenerated for one component but not shared with the agent build; corrupted embedded FS in custom builds.

Related errors


AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07). Data as JSON: /api/errors/0151890d3a0a480b. Report an issue: GitHub.

Appendix: source

Thrown at internal/support/cli/agent_command.go:257

		HostService:   agentHostService,
		Labels:        args.Filter,
	})
	// An agent is always an agent, whatever the hub in front of it is running as.
	cloudClient.SetDeployment("agent", swarmClusterID)
	cloudClient.SetStreamLogsFunc(func() bool {
		cc := notificationHandler.CloudConfig()
		return cc != nil && cc.StreamLogsEnabled()
	})
	notificationHandler.onCloudSet = cloudClient.Notify
	go cloudClient.Run(ctx)
	if apiKeyFunc() != "" {
		cloudClient.Notify()
	}

	// Create agent server using the same shared client service
	server, err := agent.NewServer(clientService, certs, args.Version(), notificationHandler)
	if err != nil {
		return fmt.Errorf("failed to create agent server: %w", err)
	}
	go func() {
		log.Info().Msgf("Dozzle agent version %s", args.Version())
		log.Info().Msgf("Agent listening on %s", listener.Addr().String())

		if err := server.Serve(listener); err != nil {
			log.Error().Err(err).Msg("failed to serve")
		}
	}()
	<-ctx.Done()
	stop()
	log.Info().Msg("Shutting down agent")
	server.Stop()
	log.Debug().Str("file", agentAddrFile).Msg("Removing agent address file")
	os.Remove(agentAddrFile)
	return nil
}

View on GitHub (pinned to d9463cbe21)