laravel/framework · error · InvalidArgumentException

Using three-part references is not supported, you may use `S

Error message

Using three-part references is not supported, you may use `Schema::connection('{$segments[0]}')` instead.

What it means

Builder::parseSchemaAndTable() throws InvalidArgumentException when the supplied reference has more than two dot-separated segments (Builder.php:756). Laravel resolves only schema.table; a third segment implies database.schema.table, which the API refuses, pointing the caller to Schema::connection() for the database portion.

Source

Thrown at src/Illuminate/Database/Schema/Builder.php:757

    {
        return $this->getCurrentSchemaListing()[0] ?? null;
    }

    /**
     * Parse the given database object reference and extract the schema and table.
     *
     * @param  string  $reference
     * @param  string|bool|null  $withDefaultSchema
     * @return array{string|null, string}
     *
     * @throws \InvalidArgumentException
     */
    public function parseSchemaAndTable($reference, $withDefaultSchema = null)
    {
        $segments = explode('.', $reference);

        if (count($segments) > 2) {
            throw new InvalidArgumentException(
                "Using three-part references is not supported, you may use `Schema::connection('{$segments[0]}')` instead."
            );
        }

        $table = $segments[1] ?? $segments[0];

        $schema = match (true) {
            isset($segments[1]) => $segments[0],
            is_string($withDefaultSchema) => $withDefaultSchema,
            $withDefaultSchema => $this->getCurrentSchemaName(),
            default => null,
        };

        return [$schema, $table];
    }

    /**
     * Get the database connection instance.

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Use Schema::connection('db_name')->... and pass only 'schema.table' (two segments).
  2. Drop the database prefix from the string and configure it via the connection instead.
  3. Strip extra segments before the call if the leading segment is the default DB.

Example fix

// before
Schema::getColumns('mydb.public.users');

// after
Schema::connection('mydb')->getColumns('public.users');
Defensive patterns

Strategy: validation

Validate before calling

if (substr_count($reference, '.') > 1) {
    [$db, $rest] = explode('.', $reference, 2);
    Schema::connection($db)->getColumns($rest);
} else {
    Schema::getColumns($reference);
}

Type guard

function isTwoPartReference(string $reference): bool
{
    return substr_count($reference, '.') <= 1;
}

Try / catch

try {
    Schema::getColumns($reference);
} catch (\InvalidArgumentException $e) {
    if (str_contains($e->getMessage(), 'three-part references')) {
        // split database segment into Schema::connection() and retry
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Passing 'db_name.schema.table' (or any reference with 2+ dots) to any schema API that calls parseSchemaAndTable: getColumns(), getIndexes(), getForeignKeys(), hasTable(), table(), dropColumns(), etc. Common with SQL Server where three-part names are idiomatic.

Common situations: SQL Server users passing database.schema.table; cross-database references on Postgres; tooling that auto-qualifies names with the database name.

Related errors


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