phacility/phabricator · error · PhutilProxyException

Invalid JSON input.

Error message

Invalid JSON input.

What it means

The SSH conduit workflow reads all of stdin and decodes it with phutil_json_decode(); failure raises a PhutilProxyException wrapping the parser exception. The expected payload is a JSON object (typically {"params": "<json-encoded params string>"}), so both the outer document and the nested params string must be valid JSON.

Source

Thrown at src/applications/conduit/ssh/ConduitSSHWorkflow.php:33

  public function execute(PhutilArgumentParser $args) {
    $time_start = microtime(true);

    $methodv = $args->getArg('method');
    if (!$methodv) {
      throw new Exception(pht('No Conduit method provided.'));
    } else if (count($methodv) > 1) {
      throw new Exception(pht('Too many Conduit methods provided.'));
    }

    $method = head($methodv);

    $json = $this->readAllInput();
    $raw_params = null;
    try {
      $raw_params = phutil_json_decode($json);
    } catch (PhutilJSONParserException $ex) {
      throw new PhutilProxyException(
        pht('Invalid JSON input.'),
        $ex);
    }

    $params = idx($raw_params, 'params', '[]');
    $params = phutil_json_decode($params);
    $metadata = idx($params, '__conduit__', array());
    unset($params['__conduit__']);

    $call = null;
    $error_code = null;
    $error_info = null;

    try {
      $call = new ConduitCall($method, $params);
      $call->setUser($this->getSSHUser());

      $result = $call->execute();

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Build the payload with a JSON encoder, e.g. printf '%s' "$(php -r 'echo json_encode(["params" => json_encode(["ids" => [1]])]);')".
  2. Validate the payload with a JSON linter (or jq .) before piping it.
  3. Remember the minimal valid payload is {} (empty object) when you have no parameters.

Example fix

# before (params not wrapped/escaped correctly)
$ echo '{"params":{"ids":[1]}' | ssh -p 2222 vcs@phab.example.com conduit maniphest.task.search
# after (outer JSON, params is a JSON string)
$ echo '{"params":"{\"constraints\":{\"ids\":[1]}}"}' | ssh -p 2222 vcs@phab.example.com conduit maniphest.task.search
Defensive patterns

Strategy: validation

Validate before calling

# Build the nested payload with encoders and validate it before piping.
PAYLOAD=$(php -r 'echo json_encode(["params" => json_encode($argv[1])]);' \
  '"{\\"constraints\\":{\\"ids\\":[1]}}"')
echo "$PAYLOAD" | jq . > /dev/null   # decode check
printf '%s' "$PAYLOAD" | ssh -p 2222 vcs@phab.example.com conduit maniphest.task.search

Prevention

When it happens

Trigger: Piping empty or truncated input; sending raw unescaped JSON for params (missing the outer wrapper); shell heredocs where quoting strips the escaped inner quotes, leaving the document malformed.

Common situations: Nested double-encoding surprises: the outer stdin is JSON and the 'params' member is itself a JSON-encoded string; constructing that by hand with echo frequently breaks escaping.

Understand the failure class

Related errors


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