phacility/phabricator · error · Exception

Almanac service, device, property, network and namespace nam

Error message

Almanac service, device, property, network and namespace names may not contain multiple consecutive periods.

What it means

Fifth rule of AlmanacNames::validateName(): the name may not contain '..' (multiple consecutive periods). Empty segments between dots would produce ambiguous, non-DNS-safe identifiers, so they are rejected outright.

Source

Thrown at src/applications/almanac/util/AlmanacNames.php:36

    }

    if (!preg_match('/^[a-z0-9.-]+\z/', $name)) {
      throw new Exception(
        pht(
          'Almanac service, device, property, network and namespace names '.
          'may only contain lowercase letters, numbers, hyphens, and '.
          'periods.'));
    }

    if (preg_match('/(^|\\.)\d+(\z|\\.)/', $name)) {
      throw new Exception(
        pht(
          'Almanac service, device, network, property and namespace names '.
          'may not have any segments containing only digits.'));
    }

    if (preg_match('/\.\./', $name)) {
      throw new Exception(
        pht(
          'Almanac service, device, property, network and namespace names '.
          '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.'));
    }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Ensure every joined component is non-empty before concatenation, or collapse empties: $name = implode('.', array_filter($parts));
  2. Manually fix the double dot: 'db..east' -> 'db.east'.
  3. Add a pre-check preg_match('/\.\./', $name) in your tooling with a clear error naming the offending input.

Example fix

// before
$name = implode('.', array($team, $env, $role)); // $env empty -> 'team..role'

// after
$name = implode('.', array_filter(array($team, $env, $role))); // skips empty parts
Defensive patterns

Strategy: validation

Validate before calling

if (preg_match('/\.\./', $name)) {
  throw new Exception('Name contains consecutive periods.');
}
// Safer construction: skip empty parts when joining.
$name = implode('.', array_filter($parts, 'strlen'));

Type guard

function hasNoConsecutivePeriods($name) {
  return strpos($name, '..') === false;
}

Try / catch

try {
  AlmanacNames::validateName($name);
} catch (Exception $ex) {
  if (preg_match('/multiple consecutive periods/', $ex->getMessage())) {
    $name = str_replace('..', '.', $name); // collapse, then re-run all rules
    AlmanacNames::validateName($name);
  } else {
    throw $ex;
  }
}

Prevention

When it happens

Trigger: Submitting names like 'db..east' or 'a...b', usually the result of string concatenation where one component was empty.

Common situations: Templates joining $env.$region.$role with an unset variable producing an empty segment; hand-typed names with double dots; pasting names with ellipsis characters normalized to dots.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/aa72131832967af3. Report an issue: GitHub.