phacility/phabricator · error · PhutilArgumentUsageException

Each item in the list of hints should be a JSON object, but

Error message

Each item in the list of hints should be a JSON object, but the item at index "%s" is not.

What it means

Thrown by `bin/repository hint` when the stdin payload decodes as valid JSON but is not a list of objects: the `foreach ($hints as $idx => $hint)` loop hits an element where `is_array($hint)` is false. Each hint entry must be a JSON object (map), not a scalar, string, or null.

Source

Thrown at src/applications/repository/management/PhabricatorRepositoryManagementHintWorkflow.php:40

    $hints = file_get_contents('php://stdin');
    if ($hints === false) {
      throw new PhutilArgumentUsageException(pht('Failed to read stdin.'));
    }

    try {
      $hints = phutil_json_decode($hints);
    } catch (Exception $ex) {
      throw new PhutilArgumentUsageException(
        pht(
          'Expected a list of hints in JSON format: %s',
          $ex->getMessage()));
    }

    $repositories = array();
    foreach ($hints as $idx => $hint) {
      if (!is_array($hint)) {
        throw new PhutilArgumentUsageException(
          pht(
            'Each item in the list of hints should be a JSON object, but '.
            'the item at index "%s" is not.',
            $idx));
      }

      try {
        PhutilTypeSpec::checkMap(
          $hint,
          array(
            'repository' => 'string|int',
            'old' => 'string',
            'new' => 'optional string|null',
            'hint' => 'string',
          ));
      } catch (Exception $ex) {
        throw new PhutilArgumentUsageException(
          pht(

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Wrap each entry in braces and the whole payload in square brackets: an array of objects.
  2. If generating from PHP, use `echo json_encode(array_values($hints));` to strip map keys.
  3. Sanity-check shape first: `jq 'type' hints.json` should say `array` and `jq '.[] | type'` should print only `object`.
  4. Remove stray scalars/nulls from the list.

Example fix

// before
$ echo '{"repository":"R1","old":"deadbeef","hint":"obsolete"}' | ./bin/repository hint
[1162] ... the item at index "repository" is not.

// after
$ echo '[{"repository":"R1","old":"deadbeef","hint":"obsolete"}]' | ./bin/repository hint
Defensive patterns

Strategy: validation

Validate before calling

jq -e 'type == "array" and all(.[]; type == "object")' hints.json >/dev/null && ./bin/repository hint < hints.json

Type guard

function is_hint_list($decoded): bool {
  if (!is_array($decoded) || array_keys($decoded) !== range(0, count($decoded) - 1)) {
    return false; // not a sequential list
  }
  foreach ($decoded as $hint) {
    if (!is_array($hint)) {
      return false;
    }
  }
  return true;
}

Prevention

When it happens

Trigger: Piping a JSON object of objects instead of an array of objects (`{"0": {...}}` or `{"r1": {...}}`); a list containing scalars like `["abc"]` or `[null]`; piping a single flat object `{"repository":...}` which iterates its scalar values; JSON produced from an associative PHP array via `json_encode` without `array_values()`.

Common situations: Scripts build `$hints[$callsign] = [...]` keyed by callsign and encode it directly, producing an object whose values iterate as scalars/arrays mixed; mixing one shorthand entry (a bare SHA string) into the list.

Related errors


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