phacility/phabricator · error · ConduitException

ERR-NO-EFFECT

ERR-NO-EFFECT

Error message

ERR-NO-EFFECT

What it means

maniphest.update throws ConduitException 'ERR-NO-EFFECT' when, after stripping the 'id' and 'phid' identification parameters, every remaining parameter coalesces to null — i.e. the request does not actually change anything. It is a defined error type for the method ('Update has no effect.') and aborts before the task is loaded and edited.

Source

Thrown at src/applications/maniphest/conduit/ManiphestUpdateConduitAPIMethod.php:67

    }

    $query = id(new ManiphestTaskQuery())
      ->setViewer($request->getUser())
      ->needSubscriberPHIDs(true)
      ->needProjectPHIDs(true);
    if ($id) {
      $query->withIDs(array($id));
    } else {
      $query->withPHIDs(array($phid));
    }
    $task = $query->executeOne();

    $params = $request->getAllParameters();
    unset($params['id']);
    unset($params['phid']);

    if (call_user_func_array('coalesce', $params) === null) {
      throw new ConduitException('ERR-NO-EFFECT');
    }

    if (!$task) {
      throw new ConduitException('ERR-BAD-TASK');
    }

    $task = $this->applyRequest($task, $request, $is_new = false);

    return $this->buildTaskInfoDictionary($task);
  }

}

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Omit null/empty fields from the params dict entirely instead of passing them as null, so at least one real change (title, priority, ownerPHID, ccPHIDs, etc.) survives.
  2. Skip the update call when the computed diff of desired vs. current values is empty — no-op updates are rejected by design.
  3. If you only need the current task state, call maniphest.query (or maniphest.search) instead of a zero-change update.

Example fix

// before
$conduit->callMethodSynchronous('maniphest.update', array(
  'id'    => $id,
  'title' => $new_title,   // $new_title is null -> ERR-NO-EFFECT
));

// after
$params = array('id' => $id);
if ($new_title !== null) {
  $params['title'] = $new_title;
}
if (count($params) > 1) {
  $conduit->callMethodSynchronous('maniphest.update', $params);
}
Defensive patterns

Strategy: validation

Validate before calling

// Strip null/empty fields; skip no-op updates entirely
$update = array_filter($params, function ($v) { return $v !== null && $v !== ''; });
unset($update['id'], $update['phid']);
if (empty($update)) {
  // nothing to change; read state instead of updating
  return $conduit->callMethodSynchronous('maniphest.query', array('ids' => array($params['id'])));
}

Try / catch

try {
  $result = $conduit->callMethodSynchronous('maniphest.update', $params);
} catch (ConduitClientException $e) {
  if ($e->getMessage() === 'ERR-NO-EFFECT') {
    // acceptable: task already in desired state; treat as success
    $result = null;
  } else {
    throw $e;
  }
}

Prevention

When it happens

Trigger: Calling maniphest.update with only identification parameters, or with all other values null/empty: array('id' => 123), or array('phid' => 'PHID-TASK-...', 'title' => null, 'priority' => null). call_user_func_array('coalesce', $params) returns null, so the exception fires.

Common situations: Generated update calls where every optional field is present but null (a common artifact of json_encode of a sparse struct). Idempotent retry loops that resend an update after the first application, or scripts that 'touch' a task without changing fields. Note this check runs BEFORE ERR-BAD-TASK, so a no-effect request to a nonexistent task reports ERR-NO-EFFECT first.

Related errors


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