{"record":{"id":"56245a32490f688e","repo":"microsoft/aspire","slug":"the-rust-app-resourcename-builds-from-manifestpath-but-its","errorCode":null,"errorMessage":"The Rust app '{resourceName}' builds from '{manifestPath}', but its symbolic links could not be fully resolved. Publishing stops rather than accepting a partially canonicalized path.","messagePattern":"The Rust app '(.+?)' builds from '(.+?)', but its symbolic links could not be fully resolved\\. Publishing stops rather than accepting a partially canonicalized path\\.","errorType":"exception","errorClass":"DistributedApplicationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Rust/RustDockerfileGenerator.cs","lineNumber":227,"sourceCode":"\n        if (Path.IsPathRooted(manifestPath))\n        {\n            throw new DistributedApplicationException(\n                $\"The Rust app '{resourceName}' builds from the absolute path '{manifestPath}'. Publishing needs a path \" +\n                $\"relative to its app directory '{workingDirectory}'.\");\n        }\n\n        var platformManifestPath = OperatingSystem.IsWindows()\n            ? manifestPath.Replace('\\\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar)\n            : manifestPath;\n\n        var filesystemWorkingDirectory = Path.GetFullPath(workingDirectory);\n        var filesystemManifest = Path.GetFullPath(platformManifestPath, workingDirectory);\n\n        if (!PathNormalizer.TryResolveSymlinks(filesystemWorkingDirectory, out var canonicalWorkingDirectory)\n            || !PathNormalizer.TryResolveSymlinks(filesystemManifest, out var canonicalManifest))\n        {\n            throw new DistributedApplicationException(\n                $\"The Rust app '{resourceName}' builds from '{manifestPath}', but its symbolic links could not be \" +\n                \"fully resolved. Publishing stops rather than accepting a partially canonicalized path.\");\n        }\n\n        // Resolve aliases first so equivalent roots such as /var and /private/var become lexically related.\n        // Then only enumerate entries below the build context to recover the spelling Docker will copy.\n        canonicalManifest = ResolveFilesystemCasing(canonicalWorkingDirectory, canonicalManifest);\n\n        var relativeManifest = Path.GetRelativePath(canonicalWorkingDirectory, canonicalManifest);\n\n        if (Path.IsPathRooted(relativeManifest)\n            || relativeManifest == \"..\"\n            || relativeManifest.StartsWith($\"..{Path.DirectorySeparatorChar}\", StringComparison.Ordinal)\n            || relativeManifest.StartsWith($\"..{Path.AltDirectorySeparatorChar}\", StringComparison.Ordinal))\n        {\n            throw new DistributedApplicationException(\n                $\"The Rust app '{resourceName}' builds from '{manifestPath}', which resolves outside its app directory \" +\n                $\"'{workingDirectory}'. Only the app directory is copied into the image.\");","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Rust/RustDockerfileGenerator.cs#L209-L245","documentation":"ValidateManifestPath calls PathNormalizer.TryResolveSymlinks on both the app working directory and the full manifest path; if either cannot be fully canonicalized it throws this DistributedApplicationException. Publishing needs fully resolved paths so it can verify the manifest lies inside the build context and compute the Docker COPY path; accepting a partially canonicalized path could silently produce a wrong or unsafe build context. The library stops rather than guessing.","triggerScenarios":"Publishing a RustAppResource when TryResolveSymlinks fails for the working directory or manifest path — e.g. dangling symlinks, symlink loops, or filesystem entries that disappear while canonicalizing (common with linked monorepo checkouts or network/overlay filesystems).","commonSituations":"App directory reached through a broken or cyclic symlink; macOS/Linux symlinked project folders (e.g. ~/projects -> /volume/projects) where resolution hits an unreadable link; container/overlay filesystems where the link target does not exist.","solutions":["Inspect and fix the symlinks in the app directory path — remove dangling or cyclic links (ls -l / readlink -f)","Replace symlinked paths with the real target directory when configuring the resource","Verify the manifest path and working directory exist and are readable before publishing"],"exampleFix":"// before\nln -s /nonexistent/target ../rust-app  # dangling symlink\nbuilder.AddRustApp(\"app\", \"../rust-app\");\n// after\nln -s /real/path/rust-app ../rust-app   # or use the real path directly\nbuilder.AddRustApp(\"app\", \"/real/path/rust-app\");","handlingStrategy":"validation","validationCode":"if (!PathNormalizer.TryResolveSymlinks(Path.GetFullPath(appDir), out _)) throw new InvalidOperationException(\"App directory contains unresolvable symlinks.\");","typeGuard":"bool HasResolvableSymlinks(string dir) => PathNormalizer.TryResolveSymlinks(Path.GetFullPath(dir), out _);","tryCatchPattern":"try { await PublishAsync(appModel); } catch (DistributedApplicationException ex) when (ex.Message.Contains(\"symbolic links\")) { log.LogError(ex, \"Unresolvable symlinks in Rust app path\"); }","preventionTips":["Run readlink -f (or equivalent) on the app directory before configuring the resource","Remove dangling or cyclic symlinks from project paths","Prefer real paths over symlinked checkouts in CI environments"],"tags":["rust","symlink","publish","path"],"backgroundTag":"file-not-found","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}