{"record":{"id":"5d6aa8a7e5184397","repo":"kataras/iris","slug":"dest-directory-s-eval-symlinks-w","errorCode":null,"errorMessage":"dest directory: %s: eval symlinks: %w","messagePattern":"dest directory: (.+?): eval symlinks: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"context/context.go","lineNumber":2429,"sourceCode":"\tif !isValidFilename {\n\t\t// Reject the input as it is invalid or unsafe.\n\t\treturn prefixDir, name, false, nil\n\t}\n\n\tif ValidExtensionRegexp != nil && !ValidExtensionRegexp.MatchString(filename) {\n\t\t// Reject the input as it is invalid or unsafe.\n\t\treturn prefixDir, name, false, nil\n\t}\n\n\tvar destPath string\n\tif prefixDir != \"\" {\n\t\t// Join the sanitized input with the destination directory.\n\t\tdestPath = filepath.Join(prefixDir, filename)\n\n\t\t// Get the canonical path of the destination directory.\n\t\tcanonicalDestDir, err := filepath.EvalSymlinks(prefixDir) // the prefix dir should exists.\n\t\tif err != nil {\n\t\t\treturn prefixDir, name, false, fmt.Errorf(\"dest directory: %s: eval symlinks: %w\", prefixDir, err)\n\t\t}\n\n\t\t// Check if the destination path is within the destination directory.\n\t\tif !strings.HasPrefix(destPath, canonicalDestDir) {\n\t\t\t// Reject the input as it is a path traversal attempt.\n\t\t\treturn prefixDir, name, false, nil\n\t\t}\n\t}\n\n\treturn destPath, filename, true, nil\n}\n\n// UploadFormFiles uploads any received file(s) from the client\n// to the system physical location \"destDirectory\".\n//\n// The second optional argument \"before\" gives caller the chance to\n// modify or cancel the *miltipart.FileHeader before saving to the disk,\n// it can be used to change a file's name based on the current request,","sourceCodeStart":2411,"sourceCodeEnd":2447,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/context/context.go#L2411-L2447","documentation":"Returned by the multipart save/upload helpers when filepath.EvalSymlinks fails to resolve the canonical path of the destination directory (prefixDir). EvalSymlinks errors if any path component does not exist or is an unresolvable symlink, meaning the configured upload destination is broken or absent. The library fails closed rather than writing to an unverified location.","triggerScenarios":"ctx.UploadFormFiles/SaveFormFile with a dest directory that does not exist, was deleted at runtime, contains a dangling symlink, or has a permission error on one of its components.","commonSituations":"Configured upload path points to a volume not mounted in the container; temp dir cleaned between restarts; symlinked upload roots removed by deploy scripts; permission-restricted directories.","solutions":["Create the destination directory with os.MkdirAll(prefixDir, 0o755) before calling the upload API.","Verify the directory exists and all symlinks resolve in your deployment.","Log the wrapped EvalSymlinks error from the message to identify the exact failing component.","Avoid dangling symlinks in the upload root; use real directories in production."],"exampleFix":"// before\ndir := cfg.UploadDir\nctx.UploadFormFiles(dir)\n// after\ndir := cfg.UploadDir\nif err := os.MkdirAll(dir, 0o755); err != nil {\n    return fmt.Errorf(\"prepare upload dir: %w\", err)\n}\nctx.UploadFormFiles(dir)","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(uploadDir); err != nil {\n    return fmt.Errorf(\"upload dir unusable: %w\", err)\n}\nif _, err := filepath.EvalSymlinks(uploadDir); err != nil {\n    return fmt.Errorf(\"upload dir symlink broken: %w\", err)\n}","typeGuard":"func uploadDirReady(dir string) bool {\n    fi, err := os.Stat(dir)\n    return err == nil && fi.IsDir()\n}","tryCatchPattern":"path, name, ok, err := ctx.SaveFormFile(fh)\nif err != nil {\n    if strings.Contains(err.Error(), \"eval symlinks\") {\n        return fmt.Errorf(\"upload destination invalid: %w\", err)\n    }\n    return err\n}","preventionTips":["Always os.MkdirAll the destination before saving uploads","Avoid symlinked upload roots in production; use real directories","Health-check the upload directory at startup, not at first upload"],"tags":["go","iris","filesystem","symlink","path"],"backgroundTag":"symlink-resolution-failed","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}