hashicorp/nomad · error

version tag %s not found for job %s

Error message

version tag %s not found for job %s

What it means

VersionByTag iterates a job's versions looking for one whose VersionTag.Name matches the requested tag. If no tagged version matches after scanning all versions, it returns this error with the tag and jobID. It is a lookup miss, not a transport failure.

Source

Thrown at api/jobs.go:288

	}
	return j.VersionsOpts(jobID, opts, q)
}

// VersionByTag is used to retrieve a job version by its VersionTag name.
func (j *Jobs) VersionByTag(jobID, tag string, q *QueryOptions) (*Job, *QueryMeta, error) {
	versions, _, qm, err := j.Versions(jobID, false, q)
	if err != nil {
		return nil, nil, err
	}

	// Find the version with the matching tag
	for _, version := range versions {
		if version.VersionTag != nil && version.VersionTag.Name == tag {
			return version, qm, nil
		}
	}

	return nil, nil, fmt.Errorf("version tag %s not found for job %s", tag, jobID)
}

type VersionsOptions struct {
	Diffs       bool
	DiffTag     string
	DiffVersion *uint64
}

func (j *Jobs) VersionsOpts(jobID string, opts *VersionsOptions, q *QueryOptions) ([]*Job, []*JobDiff, *QueryMeta, error) {
	var resp JobVersionsResponse

	qp := url.Values{}
	if opts != nil {
		qp.Add("diffs", strconv.FormatBool(opts.Diffs))
		if opts.DiffTag != "" {
			qp.Add("diff_tag", opts.DiffTag)
		}
		if opts.DiffVersion != nil {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. List job versions (jobs.Versions) and verify the tag exists
  2. Re-tag the correct version (nomad job tag or Jobs.TagVersion API)
  3. Check jobID spelling and namespace
  4. Fix tooling to create the tag before consumers query it

Example fix

// before
_, _, err := jobs.VersionByTag("web", "stable", nil) // tag never set
// after
jobs.TagVersion("web", &structs.VersionTag{Name: "stable"}, nil, nil)
_, _, err := jobs.VersionByTag("web", "stable", nil)
Defensive patterns

Strategy: type-guard

Validate before calling

versions, _, _ := jobs.Versions(jobID, false, nil, nil)
for _, v := range versions {
    if v.VersionTag != nil && v.VersionTag.Name == tag {
        // safe to call VersionByTag
    }
}

Type guard

func hasVersionTag(versions []*api.JobVersionsResponse, tag string) bool {
    for _, v := range versions {
        if v.VersionTag != nil && v.VersionTag.Name == tag {
            return true
        }
    }
    return false
}

Try / catch

v, _, err := jobs.VersionByTag(jobID, tag, nil)
if err != nil {
    if strings.Contains(err.Error(), "not found") {
        return nil // treat as missing tag, not fatal
    }
    return err
}

Prevention

When it happens

Trigger: Calling jobs.VersionByTag(jobID, tag, q) (or VersionByTagOnUpdate) where the job has no version tagged with that name — tag was never set, was overwritten, or the jobID is wrong.

Common situations: Typos in tag names; deployment tooling referencing a tag before tagging the job; tags lost after a job purge/rewrite; case sensitivity mismatch.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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