{"record":{"id":"f87f2dfe366872bc","repo":"reactiveui/refit","slug":"url-path-relativepath-must-start-with-and-be","errorCode":null,"errorMessage":"URL path {relativePath} must start with '/' and be of the form '/foo/bar/baz'","messagePattern":"URL path (.+?) must start with '/' and be of the form '/foo/bar/baz'","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Refit.Reflection/RestMethodInfoInternal.cs","lineNumber":320,"sourceCode":"    internal static PropertyInfo[] GetParameterProperties(ParameterInfo parameter) =>\n        ReflectionPropertyHelpers.GetReadablePublicInstanceProperties(parameter.ParameterType);\n\n    /// <summary>Verifies that the relative URL path is well formed and free of injection characters.</summary>\n    /// <param name=\"relativePath\">The relative URL path to validate.</param>\n    /// <param name=\"urlResolution\">The URL resolution mode; the leading-slash requirement is relaxed under <see cref=\"UrlResolutionMode.Rfc3986\"/>.</param>\n    /// <exception cref=\"ArgumentException\"><paramref name=\"relativePath\"/> contains a CR or LF character, or it does not\n    /// start with '/' under <see cref=\"UrlResolutionMode.RefitLegacy\"/>.</exception>\n    internal static void VerifyUrlPathIsSane(string relativePath, UrlResolutionMode urlResolution)\n    {\n        if (string.IsNullOrEmpty(relativePath))\n        {\n            return;\n        }\n\n        if (urlResolution == UrlResolutionMode.RefitLegacy\n            && !StringHelpers.StartsWith(relativePath, '/'))\n        {\n            throw new ArgumentException(\n                $\"URL path {relativePath} must start with '/' and be of the form '/foo/bar/baz'\");\n        }\n\n        // CRLF injection protection\n        if (!StringHelpers.ContainsCrOrLf(relativePath))\n        {\n            return;\n        }\n\n        throw new ArgumentException(\n            $\"URL path {relativePath} must not contain CR or LF characters\");\n    }\n\n    /// <summary>Adds headers from a <see cref=\"HeadersAttribute\"/> into the accumulated map.</summary>\n    /// <param name=\"headersAttribute\">The header attribute to process.</param>\n    /// <param name=\"ret\">The accumulated map, created as needed.</param>\n    internal static void AddHeaders(HeadersAttribute headersAttribute, ref Dictionary<string, string?>? ret)\n    {","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/reactiveui/refit/blob/b455f65ecc4c97d092317e349cb775f9cfc6bcdf/src/Refit.Reflection/RestMethodInfoInternal.cs#L302-L338","documentation":"Under the RefitLegacy URL resolution mode, any non-empty relative path on an HTTP attribute must begin with '/'. This guard enforces the legacy '/foo/bar' convention and also rejects CR/LF characters to prevent header/URL injection. Modern (non-legacy) mode is lenient about the leading slash.","triggerScenarios":"A [Get(\"users/{id}\")] style attribute (no leading slash) is used while RefitSettings.UrlResolution is set to UrlResolutionMode.RefitLegacy; or a path contains a CR/LF character in any mode.","commonSituations":"Upgrading from old Refit where paths without '/' were silently accepted; switching UrlResolutionMode; templated path that accidentally includes a newline (injection or bad data).","solutions":["Prefix every relative path with '/', e.g. [Get(\"/users/{id}\")].","If you rely on paths without a leading slash, switch UrlResolutionMode to the non-legacy mode in RefitSettings.","Ensure no CR/LF characters are interpolated into path templates (sanitize any data used in {path} parameters)."],"exampleFix":"// before\n[Get(\"users/{id}\")] Task<User> GetAsync(string id); // RefitLegacy -> throws\n\n// after\n[Get(\"/users/{id}\")] Task<User> GetAsync(string id);","handlingStrategy":"validation","validationCode":"static void AssertPathStartsWithSlash(string path, UrlResolutionMode mode) {\n    if (mode == UrlResolutionMode.RefitLegacy && !string.IsNullOrEmpty(path) && !path.StartsWith(\"/\"))\n        throw new InvalidOperationException($\"Path '{path}' must start with '/' in RefitLegacy mode.\");\n    if (path.IndexOfAny(new[] { '\\r', '\\n' }) >= 0)\n        throw new InvalidOperationException(\"Path must not contain CR/LF.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefix relative paths with '/' in all [Http*] attributes.","Switch to non-legacy UrlResolutionMode only intentionally and document why.","Sanitize any data interpolated into {path} parameters to strip CR/LF."],"tags":["refit","url","routing","configuration","security"],"backgroundTag":null,"analyzedSha":"b455f65ecc4c97d092317e349cb775f9cfc6bcdf","analyzedAt":"2026-08-13T21:20:57.878Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}