{"record":{"id":"44fc04479a3f70a7","repo":"stride3d/stride","slug":"base-path-must-be-non-empty-use-null-for-passthrough","errorCode":null,"errorMessage":"Base path must be non-empty (use null for passthrough).","messagePattern":"Base path must be non-empty \\(use null for passthrough\\)\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/core/Stride.Core.IO/FileSystemProvider.cs","lineNumber":37,"sourceCode":"\n    /// <summary>\n    /// 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","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/core/Stride.Core.IO/FileSystemProvider.cs#L19-L55","documentation":"FileSystemProvider.ChangeBasePath validates the new base path: null is allowed (passthrough to OS filesystem), but an empty/whitespace path or a relative path throws ArgumentException, because those silently resolve to the OS root or CWD, which is considered surprising and error-prone.","triggerScenarios":"Calling ChangeBasePath(\"\"), ChangeBasePath(\" \"), or ChangeBasePath(\"relative/dir\") on a FileSystemProvider; constructing a provider then re-basing it with a config value that is empty or relative.","commonSituations":"Config files with unset/blank base path fields; deriving base path from environment variables that are empty; passing user-supplied relative paths (e.g. './data') without resolving them first.","solutions":["Pass an absolute path (Path.GetFullPath / Path.Combine(AppContext.BaseDirectory, rel)) before calling","Pass null explicitly when passthrough to the OS filesystem is intended","Validate config values: treat empty base path config as 'use default' mapping to null, not \"\"","Catch ArgumentException and log the offending value for config diagnosis"],"exampleFix":"// before\nprovider.ChangeBasePath(config.BasePath); // may be \"\" or \"data\"\n// after\nprovider.ChangeBasePath(string.IsNullOrWhiteSpace(config.BasePath)\n    ? null\n    : Path.GetFullPath(config.BasePath));","handlingStrategy":"validation","validationCode":"bool valid = basePath is null ||\n    (!string.IsNullOrWhiteSpace(basePath) && Path.IsPathRooted(basePath));","typeGuard":null,"tryCatchPattern":"try { provider.ChangeBasePath(p); }\ncatch (ArgumentException ex) { /* log config error, fall back to null passthrough */ }","preventionTips":["Resolve relative paths with Path.GetFullPath first","Map empty config values to null, not \"\"","Validate base path config at startup"],"tags":["filesystem","path","validation","io"],"backgroundTag":"invalid-argument-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"}