{"id":56,"date":"2026-07-14T00:00:00","date_gmt":"2026-07-14T00:00:00","guid":{"rendered":"http:\/\/\/var\/www\/html\/?p=56"},"modified":"2026-07-21T01:02:32","modified_gmt":"2026-07-21T01:02:32","slug":"laravel-artisan-migrate-sqlstate-base-table-or-view-not-found-on-ubuntu-2004-lts","status":"publish","type":"post","link":"https:\/\/butitworkedlocal.com\/laravel-artisan-migrate-sqlstate-base-table-or-view-not-found-on-ubuntu-2004-lts\/","title":{"rendered":"Laravel `artisan migrate` Error: `SQLSTATE[42S02]: Base table or view not found` on Ubuntu 20.04 LTS"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>Resolve the Laravel `SQLSTATE[42S02]` error during `artisan migrate` on Ubuntu 20.04 LTS. This guide covers database connection, permissions, caching, and Docker-related fixes.<\/strong><\/p>\n\n\n<p>This troubleshooting guide addresses a common Laravel error encountered when attempting to run database migrations, specifically &quot;<code>SQLSTATE[42S02]: Base table or view not found<\/code>&quot;. This error typically indicates that Laravel cannot locate or access the expected database or a specific table within it, preventing successful schema evolution. It&#039;s a critical issue that halts development and deployment processes, often pointing to misconfigurations in database connectivity or permissions.<\/p>\n<h3>Symptom &amp; Error Signature<\/h3>\n<p>When you execute the <code>php artisan migrate<\/code> command from your Laravel project&#039;s root directory, instead of a successful migration message, you will observe an error similar to the following in your terminal:<\/p>\n<pre><code class=\"language-bash\">php artisan migrate\n\n   IlluminateDatabaseQueryException\n\n  SQLSTATE[42S02]: Base table or view not found: 1146 Table &#039;your_database.migrations&#039; doesn&#039;t exist (SQL: select `migration` from `migrations` order by `batch` asc, `migration` asc)\n\n  at vendor\/laravel\/framework\/src\/Illuminate\/Database\/Connection.php:712\n    708|         \/\/ If an exception occurs when attempting to run a query, we&#039;ll format the error\n    709|         \/\/ message to include the bindings with the query, which will make debugging\n    710|         \/\/ the data a lot easier if these errors tend to pop up a lot.\n    711|         catch (Exception $e) {\n    712|             throw new QueryException(\n    713|                 $query, $this-&gt;prepareBindings($bindings), $e\n    714|             );\n    715|         }\n    716|\n\n  Exception trace:\n\n  1   PDOException::(&quot;SQLSTATE[42S02]: Base table or view not found: 1146 Table &#039;your_database.migrations&#039; doesn&#039;t exist&quot;)\n      vendor\/laravel\/framework\/src\/Illuminate\/Database\/Connection.php:547\n\n  2   PDOStatement::execute()\n      vendor\/laravel\/framework\/src\/Illuminate\/Database\/Connection.php:547\n<\/code><\/pre>\n<p>The key parts of the error are <code>SQLSTATE[42S02]<\/code> and &quot;<code>Base table or view not found<\/code>&quot;, often specifically mentioning the <code>migrations<\/code> table, or another table if you&#039;re running specific migrations on an existing, but possibly incomplete, database.<\/p>\n<h3>Root Cause Analysis<\/h3>\n<p>The <code>SQLSTATE[42S02]<\/code> error during <code>artisan migrate<\/code> fundamentally means Laravel couldn&#039;t find a table it expected to interact with. This can stem from several underlying issues:<\/p>\n<ol>\n<li><strong>Incorrect Database Configuration<\/strong>: The most frequent cause. The <code>.env<\/code> file contains incorrect credentials (<code>DB_HOST<\/code>, <code>DB_PORT<\/code>, <code>DB_DATABASE<\/code>, <code>DB_USERNAME<\/code>, <code>DB_PASSWORD<\/code>), leading Laravel to attempt connection to a non-existent, wrong, or inaccessible database server\/database schema.<\/li>\n<li><strong>Database Not Created<\/strong>: The database specified by <code>DB_DATABASE<\/code> in your <code>.env<\/code> file simply does not exist on your MySQL or PostgreSQL server. Laravel tries to connect to it but finds no such schema.<\/li>\n<li><strong>Insufficient Database User Permissions<\/strong>: The <code>DB_USERNAME<\/code> user specified in <code>.env<\/code> lacks the necessary privileges (e.g., <code>CREATE<\/code>, <code>ALTER<\/code>, <code>DROP<\/code>) to create tables in the specified <code>DB_DATABASE<\/code>.<\/li>\n<li><strong>Configuration Cache Issues<\/strong>: Laravel caches its configuration for performance. If you&#039;ve recently changed your <code>.env<\/code> file, especially database credentials, the cached configuration might still be pointing to old, invalid settings.<\/li>\n<li><strong>Missing PHP Database Extensions<\/strong>: The required PHP Data Objects (PDO) extension for your database type (e.g., <code>php-mysql<\/code> or <code>php-pgsql<\/code>) is not installed or enabled for your PHP version.<\/li>\n<li><strong>Incorrect Working Directory<\/strong>: The <code>php artisan migrate<\/code> command is executed from a directory other than your Laravel project root, causing it to fail to load the correct <code>.env<\/code> file or application context.<\/li>\n<li><strong>Docker\/Containerization Issues<\/strong>: When running Laravel in Docker, the database service might not be properly linked, reachable, or its hostname\/port is incorrectly configured within the Laravel container&#039;s <code>.env<\/code>. Persistent volumes for the database might also be missing or misconfigured, leading to data loss on container restarts.<\/li>\n<\/ol>\n<h3>Step-by-Step Resolution<\/h3>\n<p>Follow these steps sequentially to diagnose and resolve the <code>SQLSTATE[42S02]<\/code> error.<\/p>\n<h4>1. Verify Database Existence and Connectivity<\/h4>\n<p>First, confirm that the target database actually exists on your database server and that you can connect to it.<\/p>\n<ol>\n<li><strong>Check <code>.env<\/code> file<\/strong>: Open your Laravel project&#039;s <code>.env<\/code> file and note the <code>DB_CONNECTION<\/code>, <code>DB_HOST<\/code>, <code>DB_PORT<\/code>, <code>DB_DATABASE<\/code>, <code>DB_USERNAME<\/code>, and <code>DB_PASSWORD<\/code> values.<pre><code class=\"language-env\">DB_CONNECTION=mysql # or pgsql\nDB_HOST=127.0.0.1\nDB_PORT=3306 # or 5432 for PostgreSQL\nDB_DATABASE=your_laravel_db\nDB_USERNAME=your_db_user\nDB_PASSWORD=your_db_password\n<\/code><\/pre>\n<\/li>\n<li><strong>Access your database server<\/strong>: Log in to your database server (e.g., via SSH to the machine hosting MySQL\/PostgreSQL).<\/li>\n<li><strong>Check database existence<\/strong>:<ul>\n<li><strong>For MySQL<\/strong>:<pre><code class=\"language-bash\">mysql -u your_db_user -p -h DB_HOST -P DB_PORT\n# Enter your_db_password when prompted\nSHOW DATABASES;\nUSE your_laravel_db; # Attempt to select the database\n<\/code><\/pre>\n<\/li>\n<li><strong>For PostgreSQL<\/strong>:<pre><code class=\"language-bash\">psql -U your_db_user -h DB_HOST -p DB_PORT -d your_laravel_db\n# Enter your_db_password when prompted\nl # List databases\nc your_laravel_db # Attempt to connect to the database\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li><strong>Create database if missing<\/strong>: If <code>your_laravel_db<\/code> does not appear in the list of databases or you cannot connect to it, create it manually:<ul>\n<li><strong>For MySQL<\/strong>: (Login as root or a privileged user)<pre><code class=\"language-bash\">CREATE DATABASE your_laravel_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;\n<\/code><\/pre>\n<\/li>\n<li><strong>For PostgreSQL<\/strong>: (Login as postgres or a privileged user)<pre><code class=\"language-bash\">CREATE DATABASE your_laravel_db ENCODING &#039;UTF8&#039; LC_COLLATE &#039;en_US.UTF-8&#039; LC_CTYPE &#039;en_US.UTF-8&#039; TEMPLATE template0;\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<blockquote class=\"important\"><p>Ensure that the <code>DB_HOST<\/code> is correctly set. <code>127.0.0.1<\/code> or <code>localhost<\/code> is common for local\/same-server databases. If your database is on a different server, use its IP address or hostname.<\/p>\n<\/blockquote>\n<\/li>\n<\/ol>\n<h4>2. Inspect and Correct <code>.env<\/code> Database Credentials<\/h4>\n<p>Even if the database exists, incorrect credentials will prevent Laravel from accessing it.<\/p>\n<ol>\n<li><p><strong>Re-verify <code>.env<\/code><\/strong>: Double-check <em>all<\/em> database-related entries in your <code>.env<\/code> file against your actual database server configuration. Pay close attention to:<\/p>\n<ul>\n<li><code>DB_HOST<\/code>: Should be the IP or hostname of the database server.<\/li>\n<li><code>DB_PORT<\/code>: Default is <code>3306<\/code> for MySQL, <code>5432<\/code> for PostgreSQL.<\/li>\n<li><code>DB_DATABASE<\/code>: The exact name of the database.<\/li>\n<li><code>DB_USERNAME<\/code>: The username with access to <code>DB_DATABASE<\/code>.<\/li>\n<li><code>DB_PASSWORD<\/code>: The password for <code>DB_USERNAME<\/code>.<\/li>\n<li><code>&gt; [!WARNING]<\/code> Ensure that passwords or usernames containing special characters (like <code>#<\/code>, <code>$<\/code>, <code>!<\/code>) are correctly escaped or quoted in your <code>.env<\/code> file if necessary, though Laravel generally handles this well. For robust passwords, consider avoiding some shell-special characters.<\/li>\n<\/ul>\n<\/li>\n<li><p><strong>Test connection with correct details<\/strong>: Attempt to connect to the database again using the exact values from your <code>.env<\/code> file, as shown in Step 1.<\/p>\n<\/li>\n<\/ol>\n<h4>3. Ensure Database User Privileges<\/h4>\n<p>The <code>DB_USERNAME<\/code> user must have sufficient permissions to create, alter, and drop tables within <code>your_laravel_db<\/code>.<\/p>\n<ol>\n<li><strong>Login to your database server as a privileged user<\/strong>: For example, as <code>root<\/code> for MySQL or <code>postgres<\/code> for PostgreSQL.<\/li>\n<li><strong>Grant permissions<\/strong>:<ul>\n<li><strong>For MySQL<\/strong>:<pre><code class=\"language-sql\">-- If the user doesn&#039;t exist, create it first\nCREATE USER &#039;your_db_user&#039;@&#039;DB_HOST&#039; IDENTIFIED BY &#039;your_db_password&#039;;\n-- Grant all privileges on your_laravel_db to the user\nGRANT ALL PRIVILEGES ON your_laravel_db.* TO &#039;your_db_user&#039;@&#039;DB_HOST&#039;;\nFLUSH PRIVILEGES;\n<\/code><\/pre>\nReplace <code>DB_HOST<\/code> with <code>localhost<\/code>, <code>127.0.0.1<\/code>, or <code>%<\/code> (for any host &#8211; use with caution in production).<\/li>\n<li><strong>For PostgreSQL<\/strong>:<pre><code class=\"language-sql\">-- Connect to the postgres default database\nc postgres\n-- If the user doesn&#039;t exist, create it first\nCREATE USER your_db_user WITH PASSWORD &#039;your_db_password&#039;;\n-- Grant all privileges on your_laravel_db to the user\nGRANT ALL PRIVILEGES ON DATABASE your_laravel_db TO your_db_user;\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<blockquote class=\"warning\"><p>Granting <code>ALL PRIVILEGES<\/code> is common for development. In production, consider granting only the minimum necessary privileges (<code>SELECT<\/code>, <code>INSERT<\/code>, <code>UPDATE<\/code>, <code>DELETE<\/code>, <code>CREATE<\/code>, <code>ALTER<\/code>, <code>DROP<\/code>, <code>INDEX<\/code>, <code>REFERENCES<\/code>) for better security.<\/p>\n<\/blockquote>\n<\/li>\n<\/ol>\n<h4>4. Clear Laravel Configuration Cache<\/h4>\n<p>Laravel caches configuration files to speed up application loading. If you&#039;ve recently modified <code>.env<\/code>, the cached version might be stale.<\/p>\n<ol>\n<li><strong>Navigate to your Laravel project root<\/strong>:<pre><code class=\"language-bash\">cd \/var\/www\/html\/your_laravel_app\n<\/code><\/pre>\n<\/li>\n<li><strong>Clear caches<\/strong>:<pre><code class=\"language-bash\">php artisan config:clear\nphp artisan cache:clear\nphp artisan view:clear\n# For Laravel 8+\nphp artisan optimize:clear\n<\/code><\/pre>\n<\/li>\n<li><strong>Attempt migration again<\/strong>:<pre><code class=\"language-bash\">php artisan migrate\n<\/code><\/pre>\n<\/li>\n<\/ol>\n<h4>5. Install Missing PHP Database Extensions<\/h4>\n<p>Laravel relies on PHP&#039;s PDO extensions to communicate with databases. If these are missing, connections will fail.<\/p>\n<ol>\n<li><strong>Identify your PHP version<\/strong>:<pre><code class=\"language-bash\">php -v\n<\/code><\/pre>\n(e.g., <code>PHP 7.4.3<\/code> or <code>PHP 8.1.10<\/code>)<\/li>\n<li><strong>Install the correct PDO extension<\/strong>:<ul>\n<li><strong>For MySQL<\/strong>:<pre><code class=\"language-bash\">sudo apt update\nsudo apt install php7.4-mysql # Replace 7.4 with your PHP version (e.g., php8.1-mysql)\n<\/code><\/pre>\n<\/li>\n<li><strong>For PostgreSQL<\/strong>:<pre><code class=\"language-bash\">sudo apt update\nsudo apt install php7.4-pgsql # Replace 7.4 with your PHP version (e.g., php8.1-pgsql)\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li><strong>Restart PHP-FPM or Apache<\/strong>:<ul>\n<li><strong>For Nginx with PHP-FPM<\/strong>:<pre><code class=\"language-bash\">sudo systemctl restart php7.4-fpm.service # Adjust service name for your PHP version\n<\/code><\/pre>\n<\/li>\n<li><strong>For Apache<\/strong>:<pre><code class=\"language-bash\">sudo systemctl restart apache2.service\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li><strong>Verify extension<\/strong>: You can check if the extension is loaded:<pre><code class=\"language-bash\">php -m | grep pdo_mysql # or pdo_pgsql\n<\/code><\/pre>\nIt should output <code>pdo_mysql<\/code> or <code>pdo_pgsql<\/code>.<\/li>\n<\/ol>\n<h4>6. Check File Permissions<\/h4>\n<p>Incorrect file permissions on Laravel&#039;s <code>storage<\/code> and <code>bootstrap\/cache<\/code> directories can prevent it from writing necessary files, sometimes leading to unexpected errors.<\/p>\n<ol>\n<li><strong>Navigate to your Laravel project root<\/strong>:<pre><code class=\"language-bash\">cd \/var\/www\/html\/your_laravel_app\n<\/code><\/pre>\n<\/li>\n<li><strong>Set correct ownership and permissions<\/strong>: Assuming your web server user is <code>www-data<\/code> (common on Ubuntu) and your application root is <code>\/var\/www\/html\/your_laravel_app<\/code>:<pre><code class=\"language-bash\">sudo chown -R www-data:www-data \/var\/www\/html\/your_laravel_app\nsudo find \/var\/www\/html\/your_laravel_app -type d -exec chmod 755 {} ;\nsudo find \/var\/www\/html\/your_laravel_app -type f -exec chmod 644 {} ;\nsudo chmod -R 775 \/var\/www\/html\/your_laravel_app\/storage\nsudo chmod -R 775 \/var\/www\/html\/your_laravel_app\/bootstrap\/cache\n<\/code><\/pre>\n<blockquote class=\"important\"><p>The <code>storage<\/code> and <code>bootstrap\/cache<\/code> directories, along with their contents, <em>must<\/em> be writable by the web server user. If you use a different user\/group for your web server (e.g., a custom FPM pool user), adjust <code>www-data<\/code> accordingly.<\/p>\n<\/blockquote>\n<\/li>\n<\/ol>\n<h4>7. If Using Docker\/Docker Compose<\/h4>\n<p>When deploying with Docker, network connectivity and service naming are critical.<\/p>\n<ol>\n<li><strong>Verify service names and network<\/strong>:<ul>\n<li>Open your <code>docker-compose.yml<\/code> file.<\/li>\n<li>Ensure the <code>DB_HOST<\/code> in your Laravel container&#039;s <code>.env<\/code> (or environment variables in <code>docker-compose.yml<\/code>) matches the service name of your database container (e.g., <code>db<\/code> or <code>mysql<\/code>).<\/li>\n<li>Example <code>docker-compose.yml<\/code> snippet:<pre><code class=\"language-yaml\">services:\n  app:\n    build: .\n    environment:\n      DB_HOST: db # This MUST match the database service name below\n      DB_DATABASE: your_laravel_db\n      DB_USERNAME: your_db_user\n      DB_PASSWORD: your_db_password\n    depends_on:\n      - db\n  db:\n    image: mysql:8.0 # or postgres:12\n    environment:\n      MYSQL_DATABASE: your_laravel_db\n      MYSQL_USER: your_db_user\n      MYSQL_PASSWORD: your_db_password\n      MYSQL_ROOT_PASSWORD: root_password\n    volumes:\n      - db_data:\/var\/lib\/mysql\nvolumes:\n  db_data:\n<\/code><\/pre>\n<\/li>\n<\/ul>\n<\/li>\n<li><strong>Check database container status<\/strong>:<pre><code class=\"language-bash\">docker-compose ps\n<\/code><\/pre>\nEnsure your database service (<code>db<\/code> or <code>mysql<\/code>) is <code>Up<\/code>.<\/li>\n<li><strong>Test connectivity from inside the Laravel container<\/strong>:<pre><code class=\"language-bash\">docker exec -it &lt;your_laravel_app_container_name&gt; bash\nphp artisan tinker\n<\/code><\/pre>\nInside tinker, try to connect:<pre><code class=\"language-php\">DB::connection()-&gt;getPdo();\n<\/code><\/pre>\nIf successful, it should return a PDO object. If it throws an error, it indicates a connectivity issue from within the container.<\/li>\n<li><strong>Rebuild and restart<\/strong>: Sometimes, container network issues can persist. A full rebuild and restart can help:<pre><code class=\"language-bash\">docker-compose down --volumes\ndocker-compose up --build -d\n<\/code><\/pre>\nThen, attempt <code>php artisan migrate<\/code> from <em>within<\/em> the Laravel container:<pre><code class=\"language-bash\">docker exec -it &lt;your_laravel_app_container_name&gt; php artisan migrate\n<\/code><\/pre>\n<\/li>\n<\/ol>\n<h4>8. Verify Laravel Application Path<\/h4>\n<p>Ensure you are executing <code>php artisan migrate<\/code> from the root directory of your Laravel project, where the <code>artisan<\/code> script and <code>.env<\/code> file are located.<\/p>\n<ol>\n<li><strong>Check current directory<\/strong>:<pre><code class=\"language-bash\">pwd\n<\/code><\/pre>\n<\/li>\n<li><strong>List files<\/strong>:<pre><code class=\"language-bash\">ls -F\n<\/code><\/pre>\nYou should see <code>artisan<\/code>, <code>.env<\/code>, <code>app\/<\/code>, <code>bootstrap\/<\/code>, <code>config\/<\/code>, etc. If not, <code>cd<\/code> into the correct directory.<\/li>\n<\/ol>\n<p>After performing these steps, re-run <code>php artisan migrate<\/code>. If the issue persists, carefully review your terminal output for any new error messages that might point to a different problem.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Resolve the Laravel `SQLSTATE[42S02]` error during `artisan migrate` on Ubuntu 20.04 LTS. This guide covers database connection, permissions, caching, and Docker-related fixes.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[63],"tags":[147,71,146,152,65,151,6,18],"class_list":["post-56","post","type-post","status-publish","format-standard","hentry","category-runtimes","tag-artisan","tag-database","tag-laravel","tag-migrate","tag-php","tag-sqlstate","tag-troubleshooting","tag-ubuntu-20-04"],"_links":{"self":[{"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/posts\/56","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/comments?post=56"}],"version-history":[{"count":2,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/posts\/56\/revisions"}],"predecessor-version":[{"id":303,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/posts\/56\/revisions\/303"}],"wp:attachment":[{"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/media?parent=56"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/categories?post=56"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/butitworkedlocal.com\/wp-json\/wp\/v2\/tags?post=56"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}