laravel/framework · error · InvalidArgumentException

Order direction must be a SortDirection, "asc" or "desc".

Error message

Order direction must be a SortDirection, "asc" or "desc".

What it means

Thrown by orderBy's match expression when $direction is neither a SortDirection enum case nor a string that lowercases to 'asc'/'desc'. Since the enum introduction, only those three normalized values are accepted; typos, localized strings, or uppercase variants with weird casing are caught here (note the code lowercases the string before comparing, so 'ASC' is fine, but 'ascending' or '' is not).

Source

Thrown at src/Illuminate/Database/Query/Builder.php:2992

     */
    public function orderBy($column, $direction = SortDirection::Ascending)
    {
        if ($this->isQueryable($column)) {
            [$query, $bindings] = $this->createSub($column);

            $column = new Expression('('.$query.')');

            $this->addBinding($bindings, $this->unions ? 'unionOrder' : 'order');
        }

        $direction = match (true) {
            $direction instanceof SortDirection => match ($direction) {
                SortDirection::Ascending => 'asc',
                SortDirection::Descending => 'desc',
            },
            strtolower($direction) === 'asc' => 'asc',
            strtolower($direction) === 'desc' => 'desc',
            default => throw new InvalidArgumentException('Order direction must be a SortDirection, "asc" or "desc".'),
        };

        $this->{$this->unions ? 'unionOrders' : 'orders'}[] = [
            'column' => $column,
            'direction' => $direction,
        ];

        return $this;
    }

    /**
     * Add a descending "order by" clause to the query.
     *
     * @param  \Closure|\Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder<*>|\Illuminate\Contracts\Database\Query\Expression|string  $column
     * @return $this
     */
    public function orderByDesc($column)
    {

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Use the enum: `orderBy('col', SortDirection::Descending)` or the helper `orderByDesc('col')`.
  2. Whitelist user input: `$dir = in_array(strtolower($req->dir), ['asc','desc']) ? $req->dir : 'asc';`.
  3. Pass the literal string 'asc' or 'desc'.
  4. Coerce empty/null to a default before calling orderBy.

Example fix

// before
$query->orderBy('name', $request->input('sort_dir'));
// when sort_dir=ascending => Order direction must be a SortDirection...

// after
$dir = in_array(strtolower((string) $request->input('sort_dir')), ['asc','desc'], true)
    ? strtolower((string) $request->input('sort_dir'))
    : 'asc';
$query->orderBy('name', $dir);
Defensive patterns

Strategy: validation

Validate before calling

use Illuminate\Database\Query\SortDirection;

$dir = match (strtolower((string) $input)) {
    'asc', 'ascending' => 'asc',
    'desc', 'descending' => 'desc',
    default => 'asc',
};
$query->orderBy($col, $dir);

Type guard

function isValidOrderDirection(mixed $d): bool
{
    return $d instanceof \Illuminate\Database\Query\SortDirection
        || in_array(strtolower((string) $d), ['asc','desc'], true);
}

Try / catch

// Validate the direction from user input before calling orderBy; do not try/catch.

Prevention

When it happens

Trigger: `orderBy('created_at', 'ascending')`. Passing an empty string default. Passing user-controlled input like `$request->input('dir')` directly as direction. Passing a boolean or integer as direction.

Common situations: Datatables/sortable-table controllers forwarding `?dir=...` straight into orderBy; i18n code returning translated direction words; refactoring away from magic strings to the enum but missing one call site.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/03570e4c0c03a01c.json. Report an issue: GitHub.