{"record":{"id":"e0929abaa492e849","repo":"phacility/phabricator","slug":"expected-s-or-s-got-s","errorCode":null,"errorMessage":"Expected %s or %s, got %s.","messagePattern":"Expected (.+?) or (.+?), got (.+?)\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php","lineNumber":708,"sourceCode":"            if (!preg_match($pattern, $entry, $matches)) {\n              throw new Exception(pht('Unable to parse entry!'));\n            }\n            $map[html_entity_decode($matches[2])] =\n              $this->getFileTypeFromSVNKind($matches[1]);\n            $mode = 'entry-or-end';\n          } else {\n            $entry[] = $line;\n          }\n          break;\n        case 'entry-or-end':\n          if ($line == '</list>') {\n            $done = true;\n            break 2;\n          } else if ($line == '<entry') {\n            $mode = 'entry';\n            $entry = array();\n          } else {\n            throw new Exception(\n              pht(\n                'Expected %s or %s, got %s.',\n                '</list>',\n                '<entry',\n                $line));\n          }\n          break;\n        case 'xml':\n          $expect = '/<?xml version=\"1.0\".*?>/';\n          if (!preg_match($expect, $line)) {\n            throw new Exception(\n              pht(\n                \"Expected '%s', got %s.\",\n                $expect,\n                $line));\n          }\n          $mode = 'list';\n          break;","sourceCodeStart":690,"sourceCodeEnd":726,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php#L690-L726","documentation":"The same line-oriented state machine for svn ls --xml requires that after a completed <entry>, the next line is exactly '</list>' (finish) or '<entry' (next record); anything else throws (PhabricatorRepositorySvnCommitChangeParserWorker.php:698-716). The parser assumes a fixed, unindented serialization of the XML.","triggerScenarios":"svn emitting XML with indentation, blank lines, comments, or reformatted structure between entries; warning text from svn (certificate, auth, deprecation notices) interleaved into stdout mid-stream.","commonSituations":"svn client/server upgrades changing output formatting; svn warnings printed to stdout; wrapper scripts or proxies altering the stream.","solutions":["Run svn ls --xml manually as the daemon user and inspect the lines between entries","Remove wrappers and silence svn warnings (trust the server cert, fix credentials) so only clean XML is emitted","Pin svn to a version with the expected formatting, or patch the state machine upstream"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Structural pre-flight: between entries only '</list>' and '<entry' may appear.\n//   svn ls --xml <repo-url> | grep -n -v -e '</entry>' -e '<entry' -e '</list>' -e '<lists>' -e '<?xml'\n// Any surviving line will break the parser.","typeGuard":null,"tryCatchPattern":"try {\n  $map = $this->parseSVNListXML($file_path);\n} catch (Exception $ex) {\n  // Unexpected line between entries: almost always svn warnings or new\n  // formatting. Silence warnings (cert trust, credentials) or pin svn.\n  phlog(file_get_contents($file_path));\n  throw $ex;\n}","preventionTips":["Ensure svn writes warnings to stderr, not stdout; eliminate cert/auth prompts on the daemon host","Pin svn versions whose ls --xml formatting is exact","Wrap svn invocations to assert output starts with the XML declaration before parsing"],"tags":["phabricator","svn","xml","state-machine","parsing","php"],"backgroundTag":"vcs-output-parse-failure","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}