hashicorp/nomad · error

error evaluating object: %w

Error message

error evaluating object: %w

What it means

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.

Source

Thrown at client/allocwatcher/alloc_watcher.go:597

	errorFilename := allocdir.SnapshotErrorFilename(p.prevAllocID)

	buf := make([]byte, 1024)
	for !canceled() {
		// Get the next header
		hdr, err := tr.Next()

		// Snapshot has ended
		if err == io.EOF {
			return nil
		}

		if err != nil {
			return fmt.Errorf("error streaming previous alloc %q for new alloc %q: %w",
				p.prevAllocID, p.allocID, err)
		}

		if escapes, err := escapingfs.PathEscapesAllocDir(dest, "", hdr.Name); err != nil {
			return fmt.Errorf("error evaluating object: %w", err)
		} else if escapes {
			return fmt.Errorf("archive contains object that escapes alloc dir")
		}

		if hdr.Name == errorFilename {
			// Error snapshotting on the remote side, try to read
			// the message out of the file and return it.
			errBuf := make([]byte, int(hdr.Size))
			if _, err := tr.Read(errBuf); err != nil && err != io.EOF {
				return fmt.Errorf("error streaming previous alloc %q for new alloc %q; failed reading error message: %w",
					p.prevAllocID, p.allocID, err)
			}
			return fmt.Errorf("error streaming previous alloc %q for new alloc %q: %s",
				p.prevAllocID, p.allocID, string(errBuf))
		}

		// If the header is for a directory we create the directory
		if hdr.Typeflag == tar.TypeDir {

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the snapshot archive entries (from the previous node's logs or a manual snapshot request) to find the offending object name
  2. Verify both nodes run compatible Nomad versions; upgrade mismatched clients and retry
  3. Re-run the allocation to get a fresh snapshot; if corruption persists, clean the previous alloc dir on the source node
  4. Report/patch escapingfs handling if a legitimate filename triggers the evaluator error
Defensive patterns

Strategy: type-guard

Validate before calling

func safeArchiveName(name string) error {
	if strings.Contains(name, "\x00") || !utf8.ValidString(name) {
		return fmt.Errorf("malformed archive entry %q", name)
	}
	return nil
}

Type guard

func pathStaysInAllocDir(dest, name string) bool {
	escapes, err := escapingfs.PathEscapesAllocDir(dest, "", name)
	return err == nil && !escapes
}

Try / catch

if err != nil {
	if strings.Contains(err.Error(), "error evaluating object") {
		// path safety could not be verified: do NOT extract; quarantine the snapshot
	}
	return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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