hashicorp/nomad · error

could not find destination path relative to chroot: %w

Error message

could not find destination path relative to chroot: %w

What it means

The template renderer's sandbox function chroots into the alloc dir (sandboxPath) and then computes the template's destination path relative to that chroot using filepath.Rel. filepath.Rel returns an error when the two paths cannot be made relative to each other — typically because destPath is not under sandboxPath, or the paths use incompatible forms (e.g. one relative, one absolute, or differing volume roots). The renderer returns this error and the template render fails.

Source

Thrown at client/allocrunner/taskrunner/template/renderer/template_sandbox_default.go:32

// sandbox is the non-Windows sandbox implementation, which relies on chroot.
// Although chroot is not an appropriate boundary for tasks (implicitly
// untrusted), here the only code that's executing is Nomad itself. Returns the
// new destPath inside the chroot.
func sandbox(sandboxPath, destPath string) (string, error) {

	err := syscall.Chroot(sandboxPath)
	if err != nil {
		// if the user is running in unsupported non-root configuration, we
		// can't build the sandbox, but need to handle this gracefully
		fmt.Fprintf(os.Stderr, "template-render sandbox %q not available: %v",
			sandboxPath, err)
		return destPath, nil
	}

	destPath, err = filepath.Rel(sandboxPath, destPath)
	if err != nil {
		return "", fmt.Errorf("could not find destination path relative to chroot: %w", err)
	}
	if !filepath.IsAbs(destPath) {
		destPath = "/" + destPath
	}

	return destPath, nil
}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Change the template's destination to a path inside the alloc dir (e.g. "local/foo.conf" or "NOMAD_SECRETS_DIR/...")
  2. Use a relative destination path in the template block instead of an absolute host path
  3. Check client template config (function_blacklist / disable_file_sandbox and sandbox settings) that affect sandboxPath
  4. Ensure the alloc dir path has no symlinks or irregular normalization that breaks filepath.Rel; align both paths' forms
  5. If writing outside the sandbox is truly required, evaluate whether sandboxing can be disabled for that client per security policy

Example fix

// before: template destination outside the alloc dir sandbox
template {
  data        = "..."
  destination = "/etc/app/config.conf"
}

// after: destination inside the alloc dir
template {
  data        = "..."
  destination = "local/config.conf"
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate template destinations before submitting the job
func validTemplateDest(dest string) bool {
    if filepath.IsAbs(dest) {
        return false // must be alloc-dir relative, e.g. "local/app.conf"
    }
    cleaned := filepath.Clean(dest)
    return !strings.HasPrefix(cleaned, "..") && !filepath.IsAbs(cleaned)
}
// for each template block: if !validTemplateDest(t.Destination) { return err }

Prevention

When it happens

Trigger: In sandbox(), syscall.Chroot succeeded, but filepath.Rel(sandboxPath, destPath) fails because the template's destination path is not contained within the sandbox/alloc-dir path — e.g. a template block with a destination outside the alloc dir, or mismatched relative/absolute path forms.

Common situations: Job template blocks using absolute destination paths that escape the alloc dir (e.g. destination = "/etc/foo.conf" while sandboxing is enforced); misconfigured client template options changing the sandbox path; symlinked or normalized alloc dir paths where lexical Rel cannot succeed; comparing a relative destPath against an absolute sandboxPath.

Related errors


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