hashicorp/nomad · error

Missing Log Config

Error message

Missing Log Config

What it means

Task.Validate() requires a non-nil LogConfig. The log config controls rotation/size of stdout/stderr collection; when it is nil Nomad cannot compute the task's log storage footprint (validated against the group's EphemeralDisk), so it appends this error to the multierror and rejects the task.

Source

Thrown at nomad/structs/structs.go:8279

		if conflictsWithProgressDeadline {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("KillTimout (%s) longer than the group's ProgressDeadline (%s)",
				t.KillTimeout, tg.Update.ProgressDeadline))
		}
	}
	if t.ShutdownDelay < 0 {
		mErr.Errors = append(mErr.Errors, errors.New("ShutdownDelay must be a positive value"))
	}

	// Validate the resources.
	if t.Resources == nil {
		mErr.Errors = append(mErr.Errors, errors.New("Missing task resources"))
	} else if err := t.Resources.Validate(); err != nil {
		mErr.Errors = append(mErr.Errors, err)
	}

	// Validate the log config
	if t.LogConfig == nil {
		mErr.Errors = append(mErr.Errors, errors.New("Missing Log Config"))
	} else if err := t.LogConfig.Validate(tg.EphemeralDisk); err != nil {
		mErr.Errors = append(mErr.Errors, err)
	}

	// Validate constraints and affinities.
	for idx, constr := range t.Constraints {
		if err := constr.Validate(); err != nil {
			outer := fmt.Errorf("Constraint %d validation failed: %s", idx+1, err)
			mErr.Errors = append(mErr.Errors, outer)
		}

		switch constr.Operand {
		case ConstraintDistinctHosts, ConstraintDistinctProperty:
			outer := fmt.Errorf("Constraint %d has disallowed Operand at task level: %s", idx+1, constr.Operand)
			mErr.Errors = append(mErr.Errors, outer)
		}
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Add a logs block to the task (e.g. max_files = 2, max_file_size = 10) or submit through the normal job endpoint so Nomad defaults apply.
  2. If constructing in Go, set t.LogConfig = &nomadstructs.LogConfig{MaxFiles: 2, MaxFileSizeMB: 10} before Validate.
  3. Check that you're not bypassing the canonical job canonicalization step (Jobs.Structs -> Canonicalize) which normally injects defaults.
  4. Use `nomad job validate` locally to catch it before submission.

Example fix

// before (Go)
task := &structs.Task{Name: "app", Driver: "docker"}
// after
task := &structs.Task{Name: "app", Driver: "docker"}
task.LogConfig = &structs.LogConfig{MaxFiles: 2, MaxFileSizeMB: 10}
Defensive patterns

Strategy: validation

Validate before calling

func validateTaskLogConfig(t *structs.Task) error {
	if t.LogConfig == nil {
		return fmt.Errorf("task %q: LogConfig is required", t.Name)
	}
	return nil
}

Type guard

func hasLogConfig(t *structs.Task) bool { return t != nil && t.LogConfig != nil }

Prevention

When it happens

Trigger: Registering a job where the task's LogConfig field is nil — either no logs block in HCL in contexts where defaults weren't applied, or building a Task in Go without setting LogConfig before Validate.

Common situations: Programmatic job generation that omits LogConfig (job submission via raw API/JSON where the agent's defaulting hook didn't run); writing validation tests that construct bare Task structs; versions where client-side defaulting differs from server-side validation.

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/3e7336f044151e85. Report an issue: GitHub.