phacility/phabricator · error · Exception
Unsupported action "%s".
Error message
Unsupported action "%s".
What it means
differential.createcomment validates its action parameter against a fixed map: 'accept', 'reject', 'resign', 'request_review' and 'rethink' map to modular revision transactions, while 'comment' and 'none' mean 'post the message only'. Any other non-empty action throws a plain Exception with the message 'Unsupported action "%s".', which Conduit reports as a generic call error carrying that text (there is no dedicated ERR_ code for it).
Source
Thrown at src/applications/differential/conduit/DifferentialCreateCommentConduitAPIMethod.php:80
'reject' => DifferentialRevisionRejectTransaction::TRANSACTIONTYPE,
'resign' => DifferentialRevisionResignTransaction::TRANSACTIONTYPE,
'request_review' =>
DifferentialRevisionRequestReviewTransaction::TRANSACTIONTYPE,
'rethink' => DifferentialRevisionPlanChangesTransaction::TRANSACTIONTYPE,
);
$action = $request->getValue('action');
if (isset($modular_map[$action])) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType($modular_map[$action])
->setNewValue(true);
} else if ($action) {
switch ($action) {
case 'comment':
case 'none':
break;
default:
throw new Exception(
pht(
'Unsupported action "%s".',
$action));
break;
}
}
$content = $request->getValue('message');
if (strlen($content)) {
$xactions[] = id(new DifferentialTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_COMMENT)
->attachComment(
id(new DifferentialTransactionComment())
->setContent($content));
}
// NOTE: The legacy "attach_inlines" flag is now ignored and has no
// effect. See T13513.View on GitHub (pinned to 5720a38cfe)
Solutions
- Use only the supported actions: accept, reject, resign, request_review, rethink, comment, none - or omit action entirely when only posting a message
- For abandon/close behavior use differential.closerevision or differential.revision.edit transactions instead
- Normalize the value before sending: lowercase, underscores instead of hyphens
- If you inherited an old script, audit every action literal it can emit
Example fix
// before $params = array( 'revision_id' => 456, 'action' => 'plan_changes', 'message' => 'Please rework this.', ); // after $params = array( 'revision_id' => 456, 'action' => 'rethink', 'message' => 'Please rework this.', );
Defensive patterns
Strategy: validation
Validate before calling
$allowed = array(
'accept', 'reject', 'resign',
'request_review', 'rethink', 'comment', 'none',
);
if ($action !== null && $action !== ''
&& !in_array(strtolower($action), $allowed, true)) {
throw new InvalidArgumentException('Unsupported action: '.$action);
} Try / catch
try {
$client->callMethodSynchronous('differential.createcomment', $params);
} catch (ConduitClientException $ex) {
if (strpos($ex->getMessage(), 'Unsupported action') !== false) {
// fall back to a plain comment (drop the action)
unset($params['action']);
$client->callMethodSynchronous('differential.createcomment', $params);
} else {
throw $ex;
}
} Prevention
- Keep the allowed action list next to the caller and validate before every send
- Normalize to lowercase with underscores before comparing
- Comment-only flows should omit action entirely
When it happens
Trigger: Sending action values such as 'abandon', 'claim', 'plan_changes', 'request-review', 'Accept', or any string not in {accept, reject, resign, request_review, rethink, comment, none} while also sending a non-empty message.
Common situations: Scripts written against pre-modular Phabricator where extra actions existed; copy-pasting action names from the web UI; hyphen-vs-underscore or case mismatches; client code defaulting the action to something like 'comment_or_none' when no action is intended.
Related errors
AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21).
Data as JSON: /api/errors/a94900c3152f5e16.
Report an issue: GitHub.