temporalio/temporal · error

%q service is missing in config

Error message

%q service is missing in config

What it means

Returned by serverOptions.validateConfig in temporal/server_options.go:139 when a service name requested on the server options (so.serviceNames, e.g. frontend, history, matching, worker) has no corresponding entry under the 'services' key of the loaded config. It is wrapped by 'config validation error' from loadAndValidate. This guards against starting a service whose per-service settings (rpc ports, etc.) are absent.

Source

Thrown at temporal/server_options.go:139

		config.WithEnv(so.env),
		config.WithConfigDir(so.configDir),
		config.WithZone(so.zone),
	)
	if err != nil {
		return fmt.Errorf("could not load config file: %w", err)
	}
	so.config = cfg
	return nil
}

func (so *serverOptions) validateConfig() error {
	if err := so.config.Validate(); err != nil {
		return err
	}

	for name := range so.serviceNames {
		if _, ok := so.config.Services[string(name)]; !ok {
			return fmt.Errorf("%q service is missing in config", name)
		}
	}
	return nil
}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Add a '<serviceName>:' block under 'services:' in your config with at least an rpc section (grpcPort/httpPort as needed).
  2. Or reduce the requested services via server options (e.g. run only temporal.WithFrontendService on this node) to match the config.
  3. Start from the upstream config_template.yaml and keep services sections in sync with the services your deployment runs.
  4. Check for YAML key typos ('frontend ' with trailing space, wrong case) which make the lookup miss.

Example fix

// config before — server requests history but config only has frontend
services:
  frontend:
    rpc:
      grpcPort: 7233
// after
services:
  frontend:
    rpc:
      grpcPort: 7233
  history:
    rpc:
      grpcPort: 7234
Defensive patterns

Strategy: validation

Validate before calling

requested := map[string]bool{"frontend": true, "history": true, "matching": true, "worker": true}
for svc := range requested {
    if _, ok := cfg.Services[svc]; !ok {
        return fmt.Errorf("preflight: %q not present in config services", svc)
    }
}

Try / catch

if err := server.Start(); err != nil {
    if strings.Contains(err.Error(), "is missing in config") {
        log.Fatalf("config missing a requested service: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: temporal.NewServer with default service set (or WithService/WithFrontendService etc.) combined with a config file whose services map lacks that key — e.g. a minimal config defining only 'frontend' while history/matching/worker are also requested.

Common situations: Running an all-in-one server with a config copied from a single-service example; deleting or renaming a services block; splitting a monolith config for a per-service deployment but reusing the full service list on one node.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/63b70784cce060de. Report an issue: GitHub.