phacility/phabricator · error · Exception
Almanac service, device, property, network and namespace nam
Error message
Almanac service, device, property, network and namespace names must begin and end with a letter or number.
What it means
Final rule of AlmanacNames::validateName(): the name must match /^[a-z0-9].*[a-z0-9]\z/, i.e. begin and end with a letter or digit. Leading or trailing hyphens/dots (which the earlier charset rules permit internally) make invalid DNS-label boundaries and are rejected last.
Source
Thrown at src/applications/almanac/util/AlmanacNames.php:57
'may not contain multiple consecutive periods.'));
}
if (preg_match('/\\.-|-\\./', $name)) {
throw new Exception(
pht(
'Almanac service, device, property, network and namespace names '.
'may not contain hyphens adjacent to periods.'));
}
if (preg_match('/--/', $name)) {
throw new Exception(
pht(
'Almanac service, device, property, network and namespace names '.
'may not contain multiple consecutive hyphens.'));
}
if (!preg_match('/^[a-z0-9].*[a-z0-9]\z/', $name)) {
throw new Exception(
pht(
'Almanac service, device, property, network and namespace names '.
'must begin and end with a letter or number.'));
}
}
}
View on GitHub (pinned to 5720a38cfe)
Solutions
- Trim separators from both ends after sanitizing: $name = trim($name, '-.');
- Fix by hand: '-web01' -> 'web01', 'web01.' -> 'web01'.
- Run the whole AlmanacNames rule set in your tooling before submitting so you see which rule fails first.
Example fix
// before
$name = trim(strtolower($raw), ' '); // '-web-01-' keeps edge hyphens -> throws
// after
$name = trim(preg_replace('/[^a-z0-9.-]+/', '-', strtolower($raw)), '-.'); // 'web-01' Defensive patterns
Strategy: validation
Validate before calling
if (!preg_match('/^[a-z0-9].*[a-z0-9]\z/', $name)) {
throw new Exception('Name must begin and end with a letter or number.');
}
// Prevent at construction time:
$name = trim($name, '-.'); Type guard
function hasAlphanumericEdges($name) {
return (bool)preg_match('/^[a-z0-9].*[a-z0-9]\z/', $name);
} Try / catch
try {
AlmanacNames::validateName($name);
} catch (Exception $ex) {
if (preg_match('/must begin and end with a letter or number/', $ex->getMessage())) {
$name = trim($name, '-.'); // fix edges, re-run full rule set
AlmanacNames::validateName($name);
} else {
throw $ex;
}
} Prevention
- Always trim '-.' from both ends as the final step of any slugify pipeline.
- Reject empty results after trimming instead of submitting them.
- Single-character names fail here too (regex needs 2+ chars) - combine with the length rule.
When it happens
Trigger: Names like '-web01', 'web01.', or '.web01' - often the residue of trimming or sanitizing that leaves an edge separator, e.g. trim($value, ' ') leaving '-web-'.
Common situations: Slugify pipelines that forget to trim separators from the ends; names derived from strings that start or end with separators; splitting 'env.name' and reusing the trailing part '.name'.
Related errors
- Almanac service, device, property, network and namespace nam
- Almanac service, device, property, network and namespace nam
- Almanac service, device, property, network and namespace nam
- Almanac service, device, network, property and namespace nam
- Almanac service, device, property, network and namespace nam
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/a7e3370beddec28a.
Report an issue: GitHub.