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
- Build the payload with a JSON encoder, e.g. printf '%s' "$(php -r 'echo json_encode(["params" => json_encode(["ids" => [1]])]);')".
- Validate the payload with a JSON linter (or jq .) before piping it.
- 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
- Never hand-escape the nested params string; use two passes of an encoder (json of a json string).
- Pipe the payload through jq (or json.loads) as a smoke test before every run.
- Use printf '%s' instead of echo -e to avoid backslash interpretation mangling escapes.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- No Conduit method provided.
- Too many Conduit methods provided.
- Service "%s" is unrecognized, restricted, or you do not have
- This public key is already associated with another user or d
- Conduit API method "%s" does not exist.
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/bc0542f97287aad6.
Report an issue: GitHub.