temporalio/temporal · error
invalid service %q in service list %v
Error message
invalid service %q in service list %v
What it means
Returned by serverOptions.loadAndValidate when a service name supplied via WithServices (or the services list) is not one of the known Temporal services: frontend, internal-frontend, history, matching, worker. It is a fast-fail configuration validation so an unknown/typo'd service name aborts before any config load or service startup.
Source
Thrown at temporal/server_options.go:87
}
)
func newServerOptions(opts []ServerOption) *serverOptions {
so := &serverOptions{
// Set defaults here.
persistenceServiceResolver: resolver.NewNoopResolver(),
}
for _, opt := range opts {
opt.apply(so)
}
return so
}
func (so *serverOptions) loadAndValidate() error {
for serviceName := range so.serviceNames {
if !slices.Contains(Services, string(serviceName)) {
return fmt.Errorf("invalid service %q in service list %v", serviceName, so.serviceNames)
}
}
if so.config == nil {
err := so.loadConfig()
if err != nil {
return fmt.Errorf("unable to load config: %w", err)
}
}
err := so.validateConfig()
if err != nil {
return fmt.Errorf("config validation error: %w", err)
}
return nil
}
View on GitHub (pinned to bde624efd1)
Solutions
- Use one of the exact supported names: frontend, internal-frontend, history, matching, worker (see temporal.Services in temporal/server.go)
- Fix typos and casing — the check is a plain string comparison against the Services slice
- If you intended internal-frontend, confirm your Temporal build/version supports it before including it
- If the list comes from a config file, validate its contents against the supported set before constructing the server
- If you need a custom service, that is not supported by this option set — remove the entry and rely on the standard services
Example fix
// before
srv, err := temporal.NewServer(
temporal.WithServices("front-end", "history", "matching", "worker"),
)
// invalid service "front-end" in service list [front-end history matching worker]
// after
srv, err := temporal.NewServer(
temporal.WithServices(temporal.FrontendService, "history", "matching", "worker"),
) Defensive patterns
Strategy: validation
Validate before calling
func validServices(names []string) error {
for _, n := range names {
switch n {
case "frontend", "internal-frontend", "history", "matching", "worker":
default:
return fmt.Errorf("invalid service %q; supported: frontend, internal-frontend, history, matching, worker", n)
}
}
return nil
}
// call validServices(myServices) before temporal.NewServer(temporal.WithServices(myServices...)) Try / catch
srv, err := temporal.NewServer(temporal.WithServices(names...))
if err != nil && strings.Contains(err.Error(), "invalid service") {
log.Fatalf("fix service list: %v", err)
} Prevention
- Copy service names only from the temporal.Services / DefaultServices constants in temporal/server.go
- Centralize the service list in one validated config value
- Lint/validate service names in CI before deployment
- Watch for renames across Temporal versions when upgrading
- Never free-form service names from user input into WithServices
When it happens
Trigger: Passing temporal.WithServices("frontend1"), a typo like "front-end" or "workers", or a service name valid in an older/newer Temporal version (e.g. "internal-frontend" on a build that doesn't define it) to temporal.NewServer, or listing an invalid service in the services config.
Common situations: Typos or wrong casing in WithServices arguments; copying service names from another product/version; enabling internal-frontend when the build/config doesn't support it; programmatic service selection built from a config file that contains an unexpected value.
Related errors
- %q service is missing in config
- missing current cluster metadata under clusterMetadata.Clust
- env, config, zone can not be set if configFilePath is set
- only one of certData or certFile properties should be specif
- only one of keyData or keyFile properties should be specifie
AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01).
Data as JSON: /api/errors/b3636188a2fab6f5.
Report an issue: GitHub.