How can I limit query results in hook_views_pre_execute?
No idea why setLimit(0) doesn't work as expected, but an alternative is to act as though you had limited the results to 0. When you add a contextual filter to a view, one of the options for When the filter value is NOT available is to Display contents of &quot;No results found&quot;. This seems to be handled by ArgumentPluginBase::defaultEmpty(), which looks like
public function defaultEmpty() {
  // We return with no query; this will force the empty text.
  $this-&gt;view-&gt;built = TRUE;
  $this-&gt;view-&gt;executed = TRUE;
  $this-&gt;view-&gt;result = [];
  return FALSE;
}

If you drop this snippet into hook_views_query_alter() it appears to work exactly the same! I'd wager that you could drop it into any of the views hooks, actually, and it would have the same effect.
EDIT: Whoops, forgot to say you'd want to replace $this-&gt;view with $view if you're inside of the hooks.