hashicorp/nomad · error

Invalid max template event rate given

Error message

Invalid max template event rate given

What it means

Validate() rejects a config whose MaxTemplateEventRate is the zero time.Duration. This rate limiter bounds how often template change events are emitted to the task runner; zero would either disable or break throttling, so an explicit positive value is required.

Source

Thrown at client/allocrunner/taskrunner/template/template.go:166

// Validate validates the configuration.
func (c *TaskTemplateManagerConfig) Validate() error {
	if c == nil {
		return fmt.Errorf("Nil config passed")
	} else if c.UnblockCh == nil {
		return fmt.Errorf("Invalid unblock channel given")
	} else if c.Lifecycle == nil {
		return fmt.Errorf("Invalid lifecycle hooks given")
	} else if c.Events == nil {
		return fmt.Errorf("Invalid event hook given")
	} else if c.ClientConfig == nil {
		return fmt.Errorf("Invalid client config given")
	} else if c.TaskDir == "" {
		return fmt.Errorf("Invalid task directory given: %q", c.TaskDir)
	} else if c.EnvBuilder == nil {
		return fmt.Errorf("Invalid task environment given")
	} else if c.MaxTemplateEventRate == 0 {
		return fmt.Errorf("Invalid max template event rate given")
	}

	// Once is a runner config, but in Nomad it is set per template, so all
	// templates given to a runner should have the same value for Once.
	var once bool
	for i, t := range c.Templates {
		if i == 0 {
			once = t.Once
		} else if t.Once != once {
			return fmt.Errorf("All templates should have same Once value")
		}
	}

	return nil
}

func (c *TaskTemplateManagerConfig) OnceModeEnabled() bool {
	return len(c.Templates) > 0 && c.Templates[0].Once

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set MaxTemplateEventRate to the client's configured value (e.g. from config.MaxTemplateEventRate) before calling NewTaskTemplateManager.
  2. If the client config value is unset, default it to a sane positive duration (Nomad default: 1s / time.Second) instead of leaving it zero.
  3. Guard constructors that copy client config so this field is always propagated.

Example fix

// before
cfg := &template.TaskTemplateManagerConfig{
    TaskDir: taskDir,
    EnvBuilder: eb,
}
// after
cfg := &template.TaskTemplateManagerConfig{
    TaskDir: taskDir,
    EnvBuilder: eb,
    MaxTemplateEventRate: clientConfig.MaxTemplateEventRate, // e.g. time.Second
}
Defensive patterns

Strategy: validation

Validate before calling

if cfg == nil || cfg.MaxTemplateEventRate <= 0 {
    return fmt.Errorf("template manager config needs a positive MaxTemplateEventRate")
}

Type guard

func hasRate(c *template.TaskTemplateManagerConfig) bool { return c != nil && c.MaxTemplateEventRate > 0 }

Try / catch

tm, err := template.NewTaskTemplateManager(cfg)
if err != nil {
    return fmt.Errorf("creating template manager: %w", err)
}

Prevention

When it happens

Trigger: Calling NewTaskTemplateManager with a config that never sets MaxTemplateEventRate (leaves the zero value time.Duration), or explicitly sets it to 0.

Common situations: Tests or tooling constructing TaskTemplateManagerConfig manually without copying the client's template event rate; config plumbing refactors that drop the client MaxTemplateEventRate setting.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/bd3915502a53439d. Report an issue: GitHub.