{"record":{"id":"32b8734f5cde3ce2","repo":"phacility/phabricator","slug":"version-name-s-is-not-valid-version-names-may-32b873","errorCode":null,"errorMessage":"Version name \"%s\" is not valid: version names may not start or end with a period or hyphen.","messagePattern":"Version name \"(.+?)\" is not valid: version names may not start or end with a period or hyphen\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/packages/storage/PhabricatorPackagesVersion.php","lineNumber":89,"sourceCode":"    if ($length > $max_length) {\n      throw new Exception(\n        pht(\n          'Version name \"%s\" is not valid: version names must not be '.\n          'more than %s characters long.',\n          $value,\n          new PhutilNumber($max_length)));\n    }\n\n    if (!preg_match('/^[A-Za-z0-9.-]+\\z/', $value)) {\n      throw new Exception(\n        pht(\n          'Version name \"%s\" is not valid: version names may only contain '.\n          'latin letters, digits, periods, and hyphens.',\n          $value));\n    }\n\n    if (preg_match('/^[.-]|[.-]$/', $value)) {\n      throw new Exception(\n        pht(\n          'Version name \"%s\" is not valid: version names may not start or '.\n          'end with a period or hyphen.',\n          $value));\n    }\n  }\n\n\n/* -(  PhabricatorSubscribableInterface  )----------------------------------- */\n\n\n  public function isAutomaticallySubscribed($phid) {\n    return false;\n  }\n\n\n/* -(  Policy Interface  )--------------------------------------------------- */\n","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/packages/storage/PhabricatorPackagesVersion.php#L71-L107","documentation":"Thrown by PhabricatorPackagesVersion::assertValidVersionName() when a version name starts or ends with a period or hyphen (checked with /^[.-]|[.-]$/). Such names would be ambiguous and sort oddly in the package version list, so '.1.0', '1.0-', or '-beta' are rejected even though their character set is otherwise legal.","triggerScenarios":"Creating a version whose name was produced by trimming or sanitization that left a leading/trailing separator, e.g. stripping '+1' from '1.0.0+' or '-rc' from '1.0.0-' via a regex that leaves the edge character behind.","commonSituations":"Automated sanitizers that replace forbidden characters with hyphens and forget to trim the edges; importing tags like '-WIP-' or trailing-dot typos.","solutions":["Trim leading and trailing periods/hyphens from the name before saving.","Run the sanitizer and the trim as one step: preg_replace then trim('.-').","Add the same edge check client-side so users see the rule before submit."],"exampleFix":"// before\n$name = preg_replace('/[^A-Za-z0-9.-]+/', '-', '-1.0.0-rc+2');\n// $name is now '-1.0.0-rc-2-', which throws\n\n// after\n$name = preg_replace('/[^A-Za-z0-9.-]+/', '-', '-1.0.0-rc+2');\n$name = trim($name, '.-');\n// $name is now '1.0.0-rc-2'\nPhabricatorPackagesVersion::assertValidVersionName($name);","handlingStrategy":"validation","validationCode":"$name = preg_replace('/[^A-Za-z0-9.-]+/', '-', $raw_name);\n$name = trim($name, '.-');\nPhabricatorPackagesVersion::assertValidVersionName($name);","typeGuard":"function has_no_edge_separators($name) {\n  return is_string($name)\n    && preg_match('/^[.-]|[.-]$/', $name) !== 1;\n}","tryCatchPattern":"try {\n  PhabricatorPackagesVersion::assertValidVersionName($name);\n} catch (Exception $ex) {\n  $errors[] = $ex->getMessage();\n}","preventionTips":["Always pair character sanitization with trim($name, '.-').","Never feed the raw output of a replace-based sanitizer straight to the editor.","Add the edge-separator rule to client-side validation messages."],"tags":["phabricator","packages","version","validation","sanitization"],"backgroundTag":"identifier-format-validation","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}