hashicorp/nomad · error

Deployment ID %q couldn't be updated as it does not exist

Error message

Deployment ID %q couldn't be updated as it does not exist

What it means

Returned by UpdateDeploymentStatus when the deployment ID referenced in the status update request does not exist in the state store. This is a logical/consistency error: the client tried to mark a deployment via structs.DeploymentStatusUpdate whose DeploymentID has no matching record.

Source

Thrown at nomad/state/state_store.go:4809

	}
	if req.Eval != nil {
		if err := s.nestedUpsertEval(txn, index, req.Eval); err != nil {
			return err
		}
	}

	return txn.Commit()
}

// updateDeploymentStatusImpl is used to make deployment status updates
func (s *StateStore) updateDeploymentStatusImpl(index uint64, u *structs.DeploymentStatusUpdate, txn *txn) error {
	// Retrieve deployment
	ws := memdb.NewWatchSet()
	deployment, err := s.deploymentByIDImpl(ws, u.DeploymentID, txn)
	if err != nil {
		return err
	} else if deployment == nil {
		return fmt.Errorf("Deployment ID %q couldn't be updated as it does not exist", u.DeploymentID)
	} else if !deployment.Active() {
		return fmt.Errorf("Deployment %q has terminal status %q:", deployment.ID, deployment.Status)
	}

	// Apply the new status
	copy := deployment.Copy()
	copy.Status = u.Status
	copy.StatusDescription = u.StatusDescription
	copy.ModifyIndex = index
	copy.ModifyTime = u.UpdatedAt

	// check each TaskGroup for ProgressDeadline and reset RequireProgressBy
	// to ProgressDeadline if the deployment is running or paused. This is to
	// ensure that the RequireProgressBy is reset on a deployment that has been
	// paused and resumed.
	for _, dState := range copy.TaskGroups {
		if dState == nil || dState.ProgressDeadline == 0 {
			continue

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the deployment ID exists (nomad deployment status <id>) before updating
  2. Re-fetch the deployment from the state store; drop the update if it was GC'd
  3. Ensure the job/deployment is not deregistered concurrently
  4. Re-run the deployment flow to create a fresh deployment
Defensive patterns

Strategy: validation

Validate before calling

dep, _, err := state.DeploymentByID(nil, u.DeploymentID)
if err != nil { return err }
if dep == nil {
  return fmt.Errorf("deployment %s no longer exists; skipping update", u.DeploymentID)
}

Type guard

func deploymentActive(s *state.StateStore, id string) bool {
  d, _, err := s.DeploymentByID(nil, id)
  return err == nil && d != nil && d.Active()
}

Try / catch

err := srv.raft.Apply(updateReq).Error()
if err != nil && strings.Contains(err.Error(), "does not exist") {
  // deployment was GC'd; drop the update instead of failing the eval
}

Prevention

When it happens

Trigger: DeploymentStatusUpdate raft operation with a DeploymentID that was never created or has since been garbage collected (e.g. job deregistration removed the deployment).

Common situations: Scheduler/RPC racing with job deletion; clients caching a stale deployment ID; replaying an old evaluation against a rebuilt state store.

Related errors


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