{"record":{"id":"28be546bf3d69da3","repo":"microsoft/aspire","slug":"the-filesystem-spelling-of-originalpath-could-not-be-matched","errorCode":null,"errorMessage":"The filesystem spelling of '{originalPath}' could not be matched in '{current}'.","messagePattern":"The filesystem spelling of '(.+?)' could not be matched in '(.+?)'\\.","errorType":"exception","errorClass":"DistributedApplicationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Rust/RustDockerfileGenerator.cs","lineNumber":314,"sourceCode":"            }\n            catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)\n            {\n                throw new DistributedApplicationException(\n                    $\"The filesystem spelling of '{originalPath}' could not be read from '{current}'.\",\n                    ex);\n            }\n\n            // APFS can treat canonically equivalent Unicode names as the same entry while returning the\n            // stored normalization form. Normalize only for matching, then keep the enumerated spelling.\n            var normalizedSegment = segments[i].Normalize(NormalizationForm.FormC);\n            current = entries.FirstOrDefault(entry =>\n                    string.Equals(Path.GetFileName(entry), segments[i], StringComparison.Ordinal))\n                ?? entries.FirstOrDefault(entry =>\n                    string.Equals(\n                        Path.GetFileName(entry).Normalize(NormalizationForm.FormC),\n                        normalizedSegment,\n                        StringComparison.OrdinalIgnoreCase))\n                ?? throw new DistributedApplicationException(\n                    $\"The filesystem spelling of '{originalPath}' could not be matched in '{current}'.\");\n        }\n\n        return current;\n    }\n\n    private static string BuildCargoCommand(List<string> cargoArgs)\n        => string.Join(\" \", new[] { \"cargo\", \"build\" }.Concat(cargoArgs.Select(ShellQuote)));\n\n    private static void ValidateCargoArgumentsDoNotContainCredentials(IReadOnlyList<string> cargoArgs, string resourceName)\n    {\n        for (var i = 0; i < cargoArgs.Count; i++)\n        {\n            string? configuration = null;\n            if (cargoArgs[i] == \"--config\" && i + 1 < cargoArgs.Count)\n            {\n                configuration = cargoArgs[++i];\n            }","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Rust/RustDockerfileGenerator.cs#L296-L332","documentation":"ResolveFilesystemCasing tries to match each path segment against the actual directory entries: first exactly (ordinal), then by Unicode Form-C-normalized comparison ignoring case. If no entry matches either way, the path segment does not exist on disk as spelled, and this exception is thrown so the Dockerfile never references a nonexistent file.","triggerScenarios":"WithRustApp / publish-mode generation with a DockerfileBuildAnnotation sourcePath or manifest path containing a segment whose spelling (case or Unicode normalization) does not exist in the parent directory — e.g. path says 'Main.rs' but disk has 'main.rs' on a case-sensitive FS, or a decomposed (NFD) macOS name matched against an NFC string that truly differs.","commonSituations":"Path built by string concatenation with wrong casing; files authored on macOS (NFD) deployed to case-sensitive Linux containers; typos after renaming files; file deleted after the path was configured.","solutions":["Correct the manifest/source path spelling to exactly match the on-disk name (check case and accents with ls).","Rename the file on disk to the expected spelling (git mv Main.rs main.rs).","Normalize filenames to NFC (e.g. macOS: ditto or a normalization script) when moving between APFS/HFS+ and Linux.","Re-check that the segment actually exists — it may have been deleted."],"exampleFix":"// before\nvar path = \"/app/SRC/main.rs\"; // disk has src/\n// after\nvar path = \"/app/src/main.rs\"; // matches on-disk spelling exactly","handlingStrategy":"validation","validationCode":"var fullPath = Path.GetFullPath(manifestPath);\nvar segments = fullPath.Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries);\nforeach (var seg in segments)\n    if (seg is not (\"/\" or \"~\") && !Directory.EnumerateFileSystemEntries(Path.GetDirectoryName(fullPath)!, Path.GetFileName(fullPath)).Any())\n        throw new FileNotFoundException($\"Segment '{seg}' not found with exact spelling\");","typeGuard":null,"tryCatchPattern":"try { PublishAsync(); }\ncatch (DistributedApplicationException ex) when (ex.Message.Contains(\"could not be matched\")) {\n    logger.LogError(\"A path segment spelling does not exist on disk: {Msg}\", ex.Message);\n}","preventionTips":["Copy exact file names rather than retyping them","Normalize filenames to NFC when moving between macOS and Linux","Keep paths lowercased consistently to avoid case-mismatch bugs"],"tags":["filesystem","path","unicode","dockerfile"],"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"}