{"record":{"id":"b70cb576c236edb9","repo":"phacility/phabricator","slug":"almanac-service-device-property-network-and-nam-b70cb5","errorCode":null,"errorMessage":"Almanac service, device, property, network and namespace names may not contain hyphens adjacent to periods.","messagePattern":"Almanac service, device, property, network and namespace names may not contain hyphens adjacent to periods\\.","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/applications/almanac/util/AlmanacNames.php","lineNumber":43,"sourceCode":"          'periods.'));\n    }\n\n    if (preg_match('/(^|\\\\.)\\d+(\\z|\\\\.)/', $name)) {\n      throw new Exception(\n        pht(\n          'Almanac service, device, network, property and namespace names '.\n          'may not have any segments containing only digits.'));\n    }\n\n    if (preg_match('/\\.\\./', $name)) {\n      throw new Exception(\n        pht(\n          'Almanac service, device, property, network and namespace names '.\n          'may not contain multiple consecutive periods.'));\n    }\n\n    if (preg_match('/\\\\.-|-\\\\./', $name)) {\n      throw new Exception(\n        pht(\n          'Almanac service, device, property, network and namespace names '.\n          'may not contain hyphens adjacent to periods.'));\n    }\n\n    if (preg_match('/--/', $name)) {\n      throw new Exception(\n        pht(\n          'Almanac service, device, property, network and namespace names '.\n          'may not contain multiple consecutive hyphens.'));\n    }\n\n    if (!preg_match('/^[a-z0-9].*[a-z0-9]\\z/', $name)) {\n      throw new Exception(\n        pht(\n          'Almanac service, device, property, network and namespace names '.\n          'must begin and end with a letter or number.'));\n    }","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/phacility/phabricator/blob/5720a38cfe95b00ca4be5016dd0d2f3195f4fa04/src/applications/almanac/util/AlmanacNames.php#L25-L61","documentation":"Sixth rule of AlmanacNames::validateName(): hyphens may not sit adjacent to periods, enforced by /\\.-|-\\./. Sequences like 'a-.b' or 'a.-b' are invalid in DNS labels, so names such as 'web-.east' or 'db.-node' are rejected.","triggerScenarios":"Any submitted name containing '.-' or '-.', commonly produced when a template appends '-' to an empty segment and then joins with '.', or vice versa.","commonSituations":"Name builders that suffix each component with '-' before dot-joining; sanitizers that replace a bad char with '-' right next to an existing dot ('web/1' -> 'web.1' is fine, 'web./1' -> 'web.-1' is not).","solutions":["Rewrite the offending junction: 'web-.east' -> 'web.east' or 'web-east'.","After sanitizing, collapse invalid sequences: $name = preg_replace('/(\\.-)|(-\\.)/', '.', $name);","Prefer a canonical slugify step (lowercase, replace non-alnum runs with a single '-') instead of piecemeal replacement."],"exampleFix":"// before\n$name = str_replace('/', '-', 'web./east'); // 'web.-east' -> throws\n\n// after\n$name = strtolower(preg_replace('/[^a-z0-9]+/i', '-', 'web./east')); // 'web-east'\n$name = trim($name, '-.');","handlingStrategy":"validation","validationCode":"if (preg_match('/\\.-|-\\./', $name)) {\n  throw new Exception('Hyphens may not be adjacent to periods.');\n}\n// Canonical slugify avoids the pattern entirely:\n$name = strtolower(preg_replace('/[^a-z0-9.-]+/', '-', $raw));","typeGuard":"function hasNoHyphenAdjacentToPeriod($name) {\n  return !preg_match('/\\.-|-\\./', $name);\n}","tryCatchPattern":"try {\n  AlmanacNames::validateName($name);\n} catch (Exception $ex) {\n  if (preg_match('/hyphens adjacent to periods/', $ex->getMessage())) {\n    $name = preg_replace('/\\.-|-\\./', '.', $name); // normalize, re-validate all rules\n    AlmanacNames::validateName($name);\n  } else {\n    throw $ex;\n  }\n}","preventionTips":["Replace whole invalid runs at once ('/[^a-z0-9.-]+/') instead of char-by-char.","After any sanitization, run the full validateName() before persisting.","Watch for sanitizers that emit '-' where a '.' already sits."],"tags":["almanac","validation","naming","phabricator"],"backgroundTag":"identifier-validation-failed","analyzedSha":"5720a38cfe95b00ca4be5016dd0d2f3195f4fa04","analyzedAt":"2026-08-21T05:07:25.672Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}