hashicorp/nomad · error
failed to sandbox alloc dir %q: %w
Error message
failed to sandbox alloc dir %q: %w
What it means
The template render subprocess (z_template_render.go init/readTemplate) invokes the platform-specific sandbox() before opening the template source file; when sandbox() fails (e.g. the chroot-relative destination error above), this wrapper reports that the alloc dir could not be sandboxed. It means the renderer could not securely map the source path into the alloc-dir sandbox, so it aborts rather than reading an unsandboxed path.
Source
Thrown at client/allocrunner/taskrunner/template/renderer/z_template_render.go:84
os.Exit(ExitError)
}
}
}
func readTemplate() error {
var (
sandboxPath, sourcePath string
err error
)
flags := flag.NewFlagSet("template-render", flag.ExitOnError)
flags.StringVar(&sandboxPath, "sandbox-path", "", "")
flags.StringVar(&sourcePath, "source-path", "", "")
flags.Parse(os.Args[3:])
sourcePath, err = sandbox(sandboxPath, sourcePath) // platform-specific sandboxing
if err != nil {
return fmt.Errorf("failed to sandbox alloc dir %q: %w", sandboxPath, err)
}
f, err := os.Open(sourcePath)
if err != nil {
return fmt.Errorf("failed to open source file %q: %w", sourcePath, err)
}
defer f.Close()
_, err = io.Copy(os.Stdout, f)
return err
}
func writeTemplate() (*renderer.RenderResult, error) {
var (
sandboxPath, destPath, perms, user, group string
)
View on GitHub (pinned to 482b49bf1a)
Solutions
- Inspect the wrapped inner error (often 'could not find destination path relative to chroot') and align template source/destination paths within the alloc dir
- Rewrite template block source/destination to use alloc-dir-relative paths (local/, secrets/)
- Check client alloc_dir configuration for symlinks or non-standard mounts and normalize them
- Review Nomad version changelog for template sandbox behavior changes and adjust the job spec accordingly
- Restart the allocation after fixing paths so the renderer subprocess re-runs with correct flags
Example fix
// before: template source outside alloc dir sandbox
template {
source = "/opt/templates/app.conf.tpl"
destination = "local/app.conf"
}
// after: source staged inside the alloc dir (or inlined via data)
template {
data = file("templates/app.conf.tpl") // or embed the template text
destination = "local/app.conf"
} Defensive patterns
Strategy: validation
Validate before calling
// Pre-check that template paths live under the sandbox/alloc dir before render
func pathUnderSandbox(sandboxPath, p string) error {
absSandbox, err := filepath.Abs(sandboxPath)
if err != nil { return err }
absP, err := filepath.Abs(p)
if err != nil { return err }
rel, err := filepath.Rel(absSandbox, absP)
if err != nil || strings.HasPrefix(rel, "..") {
return fmt.Errorf("path %q is not under sandbox %q", p, sandboxPath)
}
return nil
} Prevention
- Keep both template source and destination inside the alloc dir
- Avoid symlinks or unusual mounts under the client alloc_dir
- Pin template sandbox behavior expectations when upgrading Nomad; test renders in staging
- Log and alert on render subprocess failures so path misconfigurations surface early
When it happens
Trigger: readTemplate is called during subprocess init; it parses -sandbox-path and -source-path flags and calls sandbox(sandboxPath, sourcePath). Any error returned by sandbox (such as filepath.Rel failure when the source path isn't under the sandbox path) is wrapped with this message and returned, aborting the render.
Common situations: Consul Template render events where the source/destination paths don't sit inside the alloc dir; clients where chroot behaves differently than expected and path mapping fails; alloc dirs with symlinks or unusual mount points breaking path relativization; upgrades changing template sandbox behavior causing previously working templates to fail.
Related errors
- could not find destination path relative to chroot: %w
- template source path escapes alloc directory
- template destination path escapes alloc directory
- Invalid change mode. Must be one of the following: noop, sig
- failed to clean task directories after failed migration: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/517b44a0722fb746.
Report an issue: GitHub.