hashicorp/nomad · error
Disconnect cannot be configured with both lost_after and sto
Error message
Disconnect cannot be configured with both lost_after and stop_after
What it means
errStopAndLost is a job-validation error raised when a disconnect strategy configures both lost_after and stop_after. These fields are mutually exclusive: lost_after reconciles a disconnected client as 'lost', while stop_after stops the allocation — specifying both is ambiguous, so Validate rejects the job spec.
Source
Thrown at nomad/structs/group.go:26
"fmt"
"time"
"github.com/hashicorp/go-multierror"
)
const (
// ReconcileOption is used to specify the behavior of the reconciliation process
// between the original allocations and the replacements when a previously
// disconnected client comes back online.
ReconcileOptionKeepOriginal = "keep_original"
ReconcileOptionKeepReplacement = "keep_replacement"
ReconcileOptionBestScore = "best_score"
ReconcileOptionLongestRunning = "longest_running"
)
var (
// Disconnect strategy validation errors
errStopAndLost = errors.New("Disconnect cannot be configured with both lost_after and stop_after")
errNegativeLostAfter = errors.New("lost_after cannot be a negative duration")
errNegativeStopAfter = errors.New("stop_after cannot be a negative duration")
errStopAfterNonService = errors.New("stop_after can only be used with service or batch job types")
errInvalidReconcile = errors.New("reconcile option is invalid")
)
func NewDefaultDisconnectStrategy() *DisconnectStrategy {
return &DisconnectStrategy{
Replace: new(true),
Reconcile: ReconcileOptionBestScore,
}
}
// Disconnect strategy defines how both clients and server should behave in case of
// disconnection between them.
type DisconnectStrategy struct {
// Defines for how long the server will consider the unresponsive node as
// disconnected but alive instead of lost.View on GitHub (pinned to 482b49bf1a)
Solutions
- Remove either lost_after or stop_after from the disconnect block, keeping the behavior you want
- If the desired behavior is 'reconcile as lost', set only lost_after and delete stop_after
- If the desired behavior is 'stop the task', set only stop_after and delete lost_after
- Run 'nomad job validate <file>' before submitting to catch the conflict early
Example fix
// before
disconnect {
lost_after = "2h"
stop_after = "30m"
}
// after
disconnect {
stop_after = "30m"
} Defensive patterns
Strategy: validation
Validate before calling
if ds := grp.Disconnect; ds != nil && ds.LostAfter > 0 && ds.StopOnClientAfter != nil {
return fmt.Errorf("disconnect: set only one of lost_after or stop_after")
} Type guard
func hasConflictingDisconnect(ds *api.DisconnectStrategy) bool {
return ds != nil && ds.LostAfter > 0 && ds.StopOnClientAfter != nil
} Try / catch
err := client.Jobs().Validate(job, nil, nil)
if err != nil && strings.Contains(err.Error(), "both lost_after and stop_after") {
return fmt.Errorf("fix job spec: remove either lost_after or stop_after: %w", err)
} Prevention
- Keep only one of lost_after/stop_after in the disconnect block
- Run 'nomad job validate' in CI before submitting job specs
- When merging job-spec fragments, audit the disconnect block for duplicates
- Prefer stop_after (newer field) and remove legacy lost_after if the new behavior is wanted
When it happens
Trigger: Submitting a job (Job.Validate / job register or plan) whose group's disconnect block sets both lost_after (> 0) and stop_after (non-nil), checked at group.go:88 in DisconnectStrategy.Validate.
Common situations: Merging HCL/JSON fragments where one file sets lost_after and another sets stop_after; upgrading a job spec written for an older Nomad (only lost_after existed) and adding stop_after without removing lost_after; copy-paste of example disconnect configs.
Related errors
- lost_after cannot be a negative duration
- stop_after cannot be a negative duration
- Missing job ID
- Job ID contains a space
- Missing job name
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/63a08d9232fbdd95.
Report an issue: GitHub.