phacility/phabricator · error · Exception

Content source type "%s" is unknown.

Error message

Content source type "%s" is unknown.

What it means

PhabricatorContentSource::newForSource($source, $params, $force) resolves the `$source` string against all PhabricatorContentSource subclasses (keyed by each class's SOURCECONST). If the string is not a registered source constant and `$force` is false, it throws. With `$force = true` it instead returns a PhabricatorUnknownContentSource placeholder.

Source

Thrown at src/infrastructure/contentsource/PhabricatorContentSource.php:43

   * @param const The source type constant to build a source for.
   * @param array Source parameters.
   * @param bool True to suppress errors and force construction of a source
   *   even if the source type is not valid.
   * @return PhabricatorContentSource New source object.
   */
  final public static function newForSource(
    $source,
    array $params = array(),
    $force = false) {

    $map = self::getAllContentSources();
    if (isset($map[$source])) {
      $obj = clone $map[$source];
    } else {
      if ($force) {
        $obj = new PhabricatorUnknownContentSource();
      } else {
        throw new Exception(
          pht(
            'Content source type "%s" is unknown.',
            $source));
      }
    }

    $obj->source = $source;
    $obj->params = $params;

    return $obj;
  }

  public static function newFromSerialized($serialized) {
    $dict = json_decode($serialized, true);
    if (!is_array($dict)) {
      $dict = array();
    }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Use the source class's constant (e.g. PhabricatorWebContentSource::SOURCECONST) instead of a literal string.
  2. When rendering historical/stored data that may predate current sources, call `newForSource($source, $params, true)` — it degrades to PhabricatorUnknownContentSource instead of throwing.
  3. If a custom source disappeared, restore the class/extension that defines its SOURCECONST.

Example fix

// before
$source = PhabricatorContentSource::newForSource($stored_string, $params);
// after: tolerate legacy values when rendering old records
$source = PhabricatorContentSource::newForSource($stored_string, $params, true);
Defensive patterns

Strategy: fallback

Validate before calling

$map = PhabricatorContentSource::getAllContentSources();
if (!isset($map[$source_string])) {
  // legacy/unknown value: render a placeholder instead of fataling
  $source = PhabricatorContentSource::newForSource(
    $source_string, $params, $force = true);
} else {
  $source = PhabricatorContentSource::newForSource($source_string, $params);
}

Type guard

function isKnownContentSource($source) {
  $map = PhabricatorContentSource::getAllContentSources();
  return isset($map[$source]);
}

Prevention

When it happens

Trigger: Loading stored content-source data (comments, transactions) whose source string no longer exists — e.g. an application providing a source was uninstalled — or calling newForSource with a typo'd/hand-built string instead of a class's SOURCECONST, with `$force` left at its false default.

Common situations: Uninstalling an application whose content source was recorded on old records; upgrading Phabricator where a source constant was renamed; custom code constructing sources from imported/migrated data.

Related errors


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