{"record":{"id":"e39e3eb11e4bcb83","repo":"hashicorp/nomad","slug":"error-evaluating-object-w","errorCode":null,"errorMessage":"error evaluating object: %w","messagePattern":"error evaluating object: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocwatcher/alloc_watcher.go","lineNumber":597,"sourceCode":"\terrorFilename := allocdir.SnapshotErrorFilename(p.prevAllocID)\n\n\tbuf := make([]byte, 1024)\n\tfor !canceled() {\n\t\t// Get the next header\n\t\thdr, err := tr.Next()\n\n\t\t// Snapshot has ended\n\t\tif err == io.EOF {\n\t\t\treturn nil\n\t\t}\n\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error streaming previous alloc %q for new alloc %q: %w\",\n\t\t\t\tp.prevAllocID, p.allocID, err)\n\t\t}\n\n\t\tif escapes, err := escapingfs.PathEscapesAllocDir(dest, \"\", hdr.Name); err != nil {\n\t\t\treturn fmt.Errorf(\"error evaluating object: %w\", err)\n\t\t} else if escapes {\n\t\t\treturn fmt.Errorf(\"archive contains object that escapes alloc dir\")\n\t\t}\n\n\t\tif hdr.Name == errorFilename {\n\t\t\t// Error snapshotting on the remote side, try to read\n\t\t\t// the message out of the file and return it.\n\t\t\terrBuf := make([]byte, int(hdr.Size))\n\t\t\tif _, err := tr.Read(errBuf); err != nil && err != io.EOF {\n\t\t\t\treturn fmt.Errorf(\"error streaming previous alloc %q for new alloc %q; failed reading error message: %w\",\n\t\t\t\t\tp.prevAllocID, p.allocID, err)\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"error streaming previous alloc %q for new alloc %q: %s\",\n\t\t\t\tp.prevAllocID, p.allocID, string(errBuf))\n\t\t}\n\n\t\t// If the header is for a directory we create the directory\n\t\tif hdr.Typeflag == tar.TypeDir {","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocwatcher/alloc_watcher.go#L579-L615","documentation":"For every tar entry extracted from the previous allocation's snapshot, streamAllocDir validates the entry's path with escapingfs.PathEscapesAllocDir(dest, \"\", hdr.Name) to ensure it stays inside the destination alloc dir. If that validation function itself errors, the failure is wrapped as 'error evaluating object: %w' and the migration aborts, because path safety cannot be verified.","triggerScenarios":"PathEscapesAllocDir returns an error while checking a snapshot entry name: malformed archive paths (e.g. invalid or non-UTF8 names, pathological symlinks the evaluator cannot resolve), or an internal failure of the path-evaluation helper on an unusual hdr.Name.","commonSituations":"Corrupted or tampered snapshot tar from an untrusted/compromised previous node; archive produced by a different Nomad version emitting unexpected entry names; odd filenames produced by a task (control characters) that break path evaluation.","solutions":["Inspect the snapshot archive entries (from the previous node's logs or a manual snapshot request) to find the offending object name","Verify both nodes run compatible Nomad versions; upgrade mismatched clients and retry","Re-run the allocation to get a fresh snapshot; if corruption persists, clean the previous alloc dir on the source node","Report/patch escapingfs handling if a legitimate filename triggers the evaluator error"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"func safeArchiveName(name string) error {\n\tif strings.Contains(name, \"\\x00\") || !utf8.ValidString(name) {\n\t\treturn fmt.Errorf(\"malformed archive entry %q\", name)\n\t}\n\treturn nil\n}","typeGuard":"func pathStaysInAllocDir(dest, name string) bool {\n\tescapes, err := escapingfs.PathEscapesAllocDir(dest, \"\", name)\n\treturn err == nil && !escapes\n}","tryCatchPattern":"if err != nil {\n\tif strings.Contains(err.Error(), \"error evaluating object\") {\n\t\t// path safety could not be verified: do NOT extract; quarantine the snapshot\n\t}\n\treturn err\n}","preventionTips":["Avoid tasks writing control-character or extremely long filenames inside the alloc dir","Keep both source and destination clients on compatible Nomad versions","Treat this error as untrusted-input: investigate the snapshot source node","Retry with a freshly built snapshot if the archive may have been corrupted"],"tags":["security","path-validation","tar-stream"],"backgroundTag":"path-traversal-check-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"}