hashicorp/nomad · error

secret name cannot be empty

Error message

secret name cannot be empty

What it means

This error comes from the secrets (variable/secret) struct validation: a secret entry must have a non-empty Name. The validator appends this error when s.Name is ""; a companion check enforces the name matches validSecretName regex. The DECLARED AS note pointing at acl/acl.go is unrelated boilerplate — the source region here is the secret validation method in structs.go.

Source

Thrown at nomad/structs/structs.go:10631

	return &Secret{
		Name:     s.Name,
		Provider: s.Provider,
		Path:     s.Path,
		Config:   confCopy.(map[string]any),
		Env:      maps.Clone(s.Env),
	}
}

func (s *Secret) Validate() error {
	if s == nil {
		return nil
	}

	var mErr multierror.Error

	if s.Name == "" {
		_ = multierror.Append(&mErr, errors.New("secret name cannot be empty"))
	}

	if !validSecretName.MatchString(s.Name) {
		_ = multierror.Append(&mErr, fmt.Errorf("secret name must match regex %s", validSecretName))
	}

	if s.Provider == "" {
		_ = multierror.Append(&mErr, errors.New("secret provider cannot be empty"))
	}

	if s.Path == "" {
		_ = multierror.Append(&mErr, errors.New("secret path cannot be empty"))
	}

	if s.Provider == "nomad" || s.Provider == "vault" {
		if len(s.Env) > 0 {
			_ = multierror.Append(&mErr, fmt.Errorf("%s provider cannot use the env block", s.Provider))
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Provide a non-empty secret name that also matches the required regex (alphanumeric with dashes/underscores, per validSecretName).
  2. If the name is user-supplied, validate/trim input before calling the API.
  3. Check the payload field name — a typo like 'secretName' vs 'name' can leave Name empty after unmarshal.
  4. Return a clear client-side error instead of hitting the API when name is blank.

Example fix

// before
curl -X POST .../secrets -d '{"provider":"vault","path":"kv/app"}'
// after
curl -X POST .../secrets -d '{"name":"app-credentials","provider":"vault","path":"kv/app"}'
Defensive patterns

Strategy: validation

Validate before calling

var validSecretName = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_-]*$`)
func validateSecretName(name string) error {
	if name == "" {
		return fmt.Errorf("secret name cannot be empty")
	}
	if !validSecretName.MatchString(name) {
		return fmt.Errorf("secret name %q does not match required pattern", name)
	}
	return nil
}

Type guard

func hasSecretName(s *structs.Secret) bool { return s != nil && s.Name != "" }

Try / catch

if err := secret.Validate(); err != nil {
	if strings.Contains(err.Error(), "secret name cannot be empty") {
		return fmt.Errorf("please provide --name for the secret")
	}
	return err
}

Prevention

When it happens

Trigger: Creating/submitting a secret (via the secrets API endpoint or CLI) with an empty name field, or constructing the Secret struct in Go with Name unset and calling its Validate/Check path.

Common situations: API clients that build the JSON payload programmatically and leave the name key empty; CLI wrappers mapping user input where the name flag was omitted; automation that derives names from templates that rendered empty.

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/4d7f451acd786970. Report an issue: GitHub.