{"record":{"id":"78ebf6c2becbfd9e","repo":"hashicorp/nomad","slug":"job-summary-update-failed-w","errorCode":null,"errorMessage":"job summary update failed %w","messagePattern":"job summary update failed %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/state/state_store.go","lineNumber":5511,"sourceCode":"\t\treturn nil\n\t}\n\n\t// Copy and update the existing job\n\tupdated := job.Copy()\n\tupdated.Status = newStatus\n\tupdated.ModifyIndex = index\n\n\t// Insert the job\n\tif err := txn.Insert(\"jobs\", updated); err != nil {\n\t\treturn fmt.Errorf(\"job insert failed: %v\", err)\n\t}\n\tif err := txn.Insert(\"index\", &IndexEntry{\"jobs\", index}); err != nil {\n\t\treturn fmt.Errorf(\"index update failed: %v\", err)\n\t}\n\n\t// Update the children summary\n\tif err := s.setJobSummary(txn, updated, index, oldStatus, newStatus); err != nil {\n\t\treturn fmt.Errorf(\"job summary update failed %w\", err)\n\t}\n\n\t// Update the job version details. We need to make sure whenever the job summary\n\t// is updated, we also update the job's specific version. That way they do not\n\t// show different statuses.\n\tif err := s.upsertJobVersion(index, updated, txn); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (s *StateStore) setJobSummary(txn *txn, updated *structs.Job, index uint64, oldStatus, newStatus string) error {\n\tif updated.ParentID == \"\" {\n\t\treturn nil\n\t}\n\n\t// Try to update the summary of the parent job summary","sourceCodeStart":5493,"sourceCodeEnd":5529,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/state/state_store.go#L5493-L5529","documentation":"This wrapper error is produced by setJobStatus when its call to s.setJobSummary(txn, updated, index, oldStatus, newStatus) fails; it chains the inner error with %w so errors.Is/As can inspect the cause (e.g. 'job summary insert failed' or 'unknown old job status'). The entire transaction, including the job status change, is rolled back. It signals the job's summary accounting could not be kept in sync with the new status.","triggerScenarios":"A job status transition triggers setJobSummary, which itself fails (parent summary lookup error, unknown old/new status string, or summary insert failure), and setJobStatus wraps that failure with this message.","commonSituations":"Custom/patched status strings (e.g. plugins or forks injecting non-standard job statuses), state corruption, or internal bugs in summary accounting.","solutions":["Unwrap the %w chain (errors.Unwrap / %v in logs) to find the root cause","Ensure only standard JobStatus values (pending/running/dead) are ever assigned to jobs","Check for state corruption and restore from snapshot if needed","Report upstream if the root cause is a Nomad bug"],"exampleFix":"// before (custom fork assigning nonstandard status)\nupdated.Status = \"terminating\"\n// after\nupdated.Status = structs.JobStatusDead // only pending/running/dead are valid","handlingStrategy":"try-catch","validationCode":"// Ensure only valid statuses are set on jobs before submit\nif s := job.Status; s != \"\" && s != structs.JobStatusPending && s != structs.JobStatusRunning && s != structs.JobStatusDead {\n    return fmt.Errorf(\"invalid job status %q\", s)\n}","typeGuard":"func isValidJobStatus(s string) bool {\n    switch s {\n    case \"\", structs.JobStatusPending, structs.JobStatusRunning, structs.JobStatusDead:\n        return true\n    }\n    return false\n}","tryCatchPattern":"if err != nil {\n    var inner error\n    errors.As(err, &inner) // %w chain: inspect root cause (e.g. unknown job status)\n    return fmt.Errorf(\"job status change aborted: %w\", err)\n}","preventionTips":["Never invent custom job status strings in forks or tooling","Always set Status via structs.JobStatus* constants","Unwrap %w chains when diagnosing","Keep state files untouched by external tooling"],"tags":["nomad","state-store","job-summary","error-wrapping"],"backgroundTag":"job-summary-update-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}