{"record":{"id":"8de654e7ddc08200","repo":"phacility/phabricator","slug":"document-path-s-is-not-a-valid-path-the-normal","errorCode":null,"errorMessage":"Document path \"%s\" is not a valid path. The normalized form of this path is \"%s\".","messagePattern":"Document path \"(.+?)\" is not a valid path\\. The normalized form of this path is \"(.+?)\"\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/phriction/query/PhrictionDocumentQuery.php","lineNumber":272,"sourceCode":"      );\n\n      $paths = array();\n      foreach ($sets as $set) {\n        $set_paths = $set['paths'];\n        if ($set_paths === null) {\n          continue;\n        }\n\n        if (!$set_paths) {\n          throw new PhabricatorEmptyQueryException(\n            pht('No parent/ancestor paths specified.'));\n        }\n\n        $is_parents = $set['parents'];\n        foreach ($set_paths as $path) {\n          $path_normal = PhabricatorSlug::normalize($path);\n          if ($path !== $path_normal) {\n            throw new Exception(\n              pht(\n                'Document path \"%s\" is not a valid path. The normalized '.\n                'form of this path is \"%s\".',\n                $path,\n                $path_normal));\n          }\n\n          $depth = PhabricatorSlug::getDepth($path_normal);\n          if ($is_parents) {\n            $min_depth = $depth + 1;\n            $max_depth = $depth + 1;\n          } else {\n            $min_depth = $depth + 1;\n            $max_depth = null;\n          }\n\n          $paths[] = array(\n            $path_normal,","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/phriction/query/PhrictionDocumentQuery.php#L254-L290","documentation":"PhrictionDocumentQuery's withPaths() and withAncestorPaths() require caller-supplied paths to already be in canonical normalized form. During query execution each path is compared against PhabricatorSlug::normalize(); any difference (case, trailing slash, spaces, missing leading slash) aborts the query, with the expected form echoed in the message. The strictness guarantees callers cannot silently query textual variants of one logical path.","triggerScenarios":"Passing raw user input or hand-built path strings to PhrictionDocumentQuery::withPaths()/withAncestorPaths() without normalizing first; paths assembled with string concatenation or copied from external URLs.","commonSituations":"Custom applications embedding Phriction searches; wiki paths imported from external tools with different casing rules (e.g. MediaWiki); templates that render paths differently from how they store them.","solutions":["Wrap every path in PhabricatorSlug::normalize() before adding it to the query","Use the normalized form printed in the exception message as the canonical value to store and pass","Centralize path construction in one helper that always normalizes"],"exampleFix":"// before: raw path passed straight into the query\n$docs = id(new PhrictionDocumentQuery())\n  ->setViewer($viewer)\n  ->withPaths(array($path))\n  ->execute();\n\n// after: normalize before querying\n$docs = id(new PhrictionDocumentQuery())\n  ->setViewer($viewer)\n  ->withPaths(array(PhabricatorSlug::normalize($path)))\n  ->execute();","handlingStrategy":"type-guard","validationCode":"$paths = array_map('PhabricatorSlug::normalize', $paths);\n$docs = id(new PhrictionDocumentQuery())\n  ->setViewer($viewer)\n  ->withPaths($paths)\n  ->execute();","typeGuard":"function isNormalizedPhrictionSlug($slug) {\n  return is_string($slug) && $slug === PhabricatorSlug::normalize($slug);\n}\n\n// assert(all($paths, 'isNormalizedPhrictionSlug')) before withPaths()","tryCatchPattern":null,"preventionTips":["Normalize at the boundary: the moment a path enters your code, not at query time","Store only normalized slugs in your own tables and link metadata","Add the type guard to test suites that exercise phriction queries"],"tags":["phabricator","phriction","slug","normalization","query-validation"],"backgroundTag":"non-normalized-identifier","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}