{"record":{"id":"64a59cd56f312747","repo":"hashicorp/nomad","slug":"failed-to-resolve-alloc-directory-w","errorCode":null,"errorMessage":"failed to resolve alloc directory: %w","messagePattern":"failed to resolve alloc directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocdir/alloc_dir.go","lineNumber":418,"sourceCode":"\t\t\tName:     info.Name(),\n\t\t\tIsDir:    info.IsDir(),\n\t\t\tSize:     info.Size(),\n\t\t\tFileMode: info.Mode().String(),\n\t\t\tModTime:  info.ModTime(),\n\t\t}\n\t}\n\treturn files, err\n}\n\n// sanitizePath checks that the path does not escape the alloc directory,\n// does not read into the secrets or private directories and returns an absolute\n// path of the provided path.\nfunc (a *AllocDir) sanitizePath(path string) (string, error) {\n\t// In some non linux systmes, directories like /var and /tmp resolve to\n\t// /private/var and /private/tmp.\n\tresolvedAllocDir, err := filepath.EvalSymlinks(a.AllocDir)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to resolve alloc directory: %w\", err)\n\t}\n\n\trequestedPath, err := filepath.Abs(filepath.Join(resolvedAllocDir, path))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to resolve requested path: %w\", err)\n\t}\n\n\tif err := escapingfs.ChildEscapesParentDir(resolvedAllocDir, requestedPath); err != nil {\n\t\treturn \"\", fmt.Errorf(\"path escapes the alloc directory\")\n\t}\n\n\ta.mu.RLock()\n\tdefer a.mu.RUnlock()\n\n\t// Check it does not access the secrets or private directories\n\tfor _, taskDir := range a.TaskDirs {\n\t\trps := strings.ReplaceAll(requestedPath, \"/Secrets\", \"/secrets\")\n\t\tif err := escapingfs.ChildEscapesParentDir(taskDir.SecretsDir, rps); err == nil {","sourceCodeStart":400,"sourceCodeEnd":436,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocdir/alloc_dir.go#L400-L436","documentation":"AllocDir.sanitizePath() resolves the alloc directory via filepath.EvalSymlinks before validating client-supplied paths. If the alloc dir cannot be resolved (it does not exist or a symlink component is broken/unreadable), this wrapped error is returned.","triggerScenarios":"Calling List, Stat, ReadAt, BlockUntilExists or ChangeEvents when filepath.EvalSymlinks(a.AllocDir) fails — typically because the alloc dir no longer exists (destroyed) or contains an unresolvable symlink.","commonSituations":"Filesystem API calls racing with allocation GC/Destroy which removed the alloc dir; host-dir paths that are dangling symlinks; permission issues preventing traversal of the alloc dir path.","solutions":["Verify the alloc dir still exists before issuing API calls; avoid racing with Destroy/GC","Check that the alloc dir path and all symlink components are readable and resolvable","Fix or remove dangling symlinks in the path","Re-create the alloc dir via Build() if it was removed unintentionally"],"exampleFix":"// before\nf, err := allocDir.ReadAt(path, offset)\n// after\nif _, err := os.Stat(allocDir.AllocDir); err != nil {\n    return nil, fmt.Errorf(\"alloc dir gone: %w\", err)\n}\nf, err := allocDir.ReadAt(path, offset)","handlingStrategy":"validation","validationCode":"if _, err := filepath.EvalSymlinks(allocDir.AllocDir); err != nil {\n    return fmt.Errorf(\"alloc dir unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"out, err := allocDir.List(relPath)\nif err != nil && strings.Contains(err.Error(), \"failed to resolve alloc directory\") {\n    // alloc dir destroyed/GC'd: stop polling instead of retrying forever\n    return ErrAllocDirGone\n}","preventionTips":["Stop file API polling when the allocation is terminal or GC'd","Avoid dangling symlinks in the alloc dir path components","Confirm alloc dir exists before issuing read APIs","Handle the alloc-dir-destroyed case distinctly from retryable errors"],"tags":["filesystem","symlink","path-resolution"],"backgroundTag":"path-resolution-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"}