{"record":{"id":"6c2cac6adfd775ac","repo":"stride3d/stride","slug":"base-path-must-be-absolute-got-basepath","errorCode":null,"errorMessage":"Base path must be absolute, got '{basePath}'.","messagePattern":"Base path must be absolute, got '(.+?)'\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.IO/FileSystemProvider.cs","lineNumber":39,"sourceCode":"    /// Initializes a new instance of the <see cref=\"FileSystemProvider\" /> class with the given base path.\n    /// </summary>\n    /// <param name=\"rootPath\">The root path of this provider.</param>\n    /// <param name=\"localBasePath\">The path to a local directory where this instance will load the files from.</param>\n    public FileSystemProvider(string rootPath, string? localBasePath) : base(rootPath)\n    {\n        ChangeBasePath(localBasePath);\n    }\n\n    public void ChangeBasePath(string? basePath)\n    {\n        // Empty resolves to OS filesystem root, relative resolves to CWD — both surprising.\n        // null stays allowed (constructor passthrough mode).\n        if (basePath is not null)\n        {\n            if (string.IsNullOrWhiteSpace(basePath))\n                throw new ArgumentException(\"Base path must be non-empty (use null for passthrough).\", nameof(basePath));\n            if (!Path.IsPathRooted(basePath))\n                throw new ArgumentException($\"Base path must be absolute, got '{basePath}'.\", nameof(basePath));\n        }\n\n        localBasePath = basePath?.Replace(AltDirectorySeparatorChar, DirectorySeparatorChar);\n\n        // Ensure localBasePath ends with a \\\n        if (localBasePath?.EndsWith(DirectorySeparatorChar) == false)\n            localBasePath += DirectorySeparatorChar;\n    }\n\n    protected virtual string ConvertUrlToFullPath(string url)\n    {\n        if (localBasePath == null)\n            return url;\n        return localBasePath + url.Replace(VirtualFileSystem.DirectorySeparatorChar, DirectorySeparatorChar);\n    }\n\n    protected virtual string ConvertFullPathToUrl(string path)\n    {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.IO/FileSystemProvider.cs#L21-L57","documentation":"FileSystemProvider's ChangeBasePath validates a new base path. Passing a relative path (or empty string) is rejected because all file URLs would be resolved against it; only an absolute path — or null for pure passthrough mode — is allowed.","triggerScenarios":"Calling ChangeBasePath with a value like \"data\" or \"./data\" that fails Path.IsPathRooted, or with an empty/whitespace string.","commonSituations":"Building a base path by string concatenation without a root (e.g. joining a config folder name to a filename), reading basePath from config where an env var is unset, or passing \"\" intending 'no base path' instead of null.","solutions":["Prefix the path with the application's root directory (Path.GetFullPath or combining with AppContext.BaseDirectory / a known mount point)","Pass null instead of \"\" when passthrough (no base path rewriting) is intended","Trim/validate the configured value before calling ChangeBasePath"],"exampleFix":"// before\nprovider.ChangeBasePath(config.BasePath); // \"data\"\n// after\nvar full = Path.IsPathRooted(config.BasePath) ? config.BasePath : Path.Combine(AppContext.BaseDirectory, config.BasePath);\nprovider.ChangeBasePath(full);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(basePath)) throw new ArgumentException(\"Base path must be non-empty; use null for passthrough.\");\nif (!Path.IsPathRooted(basePath)) basePath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, basePath));","typeGuard":"static bool IsUsableBasePath(string p) => p is null || (p.Length > 0 && Path.IsPathRooted(p));","tryCatchPattern":null,"preventionTips":["Always run configured paths through Path.GetFullPath before handing them to the provider","Use null (not \"\") to mean 'no base path'","Log/validate config-derived paths at startup"],"tags":["io","argument-validation","path"],"backgroundTag":"invalid-config-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}