hashicorp/nomad · error

Duplicate default identities found

Error message

Duplicate default identities found

What it means

Task.Canonicalize is supposed to move the default workload identity (name "default") out of the Identities slice; if Task.Validate still sees an identity named WorkloadIdentityDefaultName inside t.Identities, it reports 'Duplicate default identities found'. It means both an implicit/default identity and an explicit identities entry named 'default' exist.

Source

Thrown at nomad/structs/structs.go:8436

			mErr.Errors = append(mErr.Errors, fmt.Errorf("CSIPluginConfig StagePublishBaseDir must not be a subdirectory of MountDir, got: StagePublishBaseDir=\"%s\" MountDir=\"%s\"", t.CSIPluginConfig.StagePublishBaseDir, t.CSIPluginConfig.MountDir))
		}

		// TODO: Investigate validation of the PluginMountDir. Not much we can do apart from check IsAbs until after we understand its execution environment though :(
	}

	// Validate default Identity
	if t.Identity != nil {
		if err := t.Identity.Validate(); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Identity %q is invalid: %w", t.Identity.Name, err))
		}
	}

	// Validate Identities
	for _, wid := range t.Identities {
		// Task.Canonicalize should move the default identity out of the Identities
		// slice, so if one is found that means it is a duplicate.
		if wid.Name == WorkloadIdentityDefaultName {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Duplicate default identities found"))
		}

		if err := wid.Validate(); err != nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Identity %q is invalid: %w", wid.Name, err))
		}
	}

	secrets := make(map[string]bool)
	for _, s := range t.Secrets {
		if _, ok := secrets[s.Name]; ok {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Duplicate secret %q found", s.Name))
		} else {
			secrets[s.Name] = true
		}

		if s.Provider == SecretProviderVault && t.Vault == nil {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("Secret %q has provider \"vault\" but no vault block", s.Name))
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove the identities entry named "default" and configure the top-level identity block instead
  2. Rename the extra entry if a distinct identity is intended (it must not be called "default")
  3. If building Tasks programmatically, call Canonicalize() before Validate/submit

Example fix

// before
identity {
  env = true
}
identities = [{ name = "default", aud = ["foo"] }]
// after
identity {
  env = true
  aud = ["foo"]
}
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
for _, wid := range t.Identities {
    if wid.Name == "default" {
        return errors.New("do not list an identity named \"default\"; use the identity block")
    }
    if seen[wid.Name] { return fmt.Errorf("duplicate identity %q", wid.Name) }
    seen[wid.Name] = true
}

Type guard

func hasDefaultIdentity(ids []*structs.WorkloadIdentity) bool {
    for _, w := range ids { if w.Name == "default" { return true } }
    return false
}

Prevention

When it happens

Trigger: A task that defines identity { } AND lists an identity named "default" in its identities list; submitting a pre-canonicalized Task struct via the API where canonicalization didn't run or the duplicate was added after.

Common situations: Hand-built JSON job payloads sent to the Nomad API that include identities: [{"name":"default"}] alongside identity block; tooling that merges identity blocks; jobspecs migrated between versions duplicating the default.

Related errors


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