{"id":2157,"date":"2015-03-23T06:27:41","date_gmt":"2015-03-23T06:27:41","guid":{"rendered":"http:\/\/kedar.nitty-witty.com\/?p=2157"},"modified":"2023-11-20T13:27:20","modified_gmt":"2023-11-20T13:27:20","slug":"solutions-mysql-error-1449-the-user-specified-as-a-definer-does-not-exist","status":"publish","type":"post","link":"https:\/\/kedar.nitty-witty.com\/blog\/solutions-mysql-error-1449-the-user-specified-as-a-definer-does-not-exist","title":{"rendered":"How to fix definer does not exist error 1449 MySQL"},"content":{"rendered":"\n<p>MySQL error 1449 occurs when a stored procedure, view, or event has been defined with a user as the definer, but that user does not exist. When such an object is executed, MySQL tries to execute it using the definer&#8217;s privileges. If the definer does not exist, then MySQL cannot execute the object and throws error 1449. To fix this error, the definer of the object should be changed to a valid user. This post will provide you with 3 possible solutions for the error:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><br><b>MySQL error 1449: The user specified as a definer does not exist.<\/b><\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>MySQL error 1449, commonly referred to as the &#8216;Definer Does Not Exist&#8217; error, can be a challenging situation for DBAs and developers. This error arises when a stored procedure, view, or event references a non-existent user as the definer. In this article, we&#8217;ll delve into the root causes of this error and provide actionable solutions to rectify it effectively.<br>I wrote about <a href=\"http:\/\/kedar.nitty-witty.com\/access-control-in-mysql-stored-routines-by-example-definer-invoker-sql-security\" target=\"_blank\" rel=\"noopener\">DEFINER &amp; INVOKER SQL SECURITY in MySQL<\/a> long back in early 2012 which covers the explanation of how they work with respect to the stored routines in MySQL!<\/p>\n\n\n\n<p>Here I&#8217;ll try to extend it little more with examples for the error and provide 3 solutions.<br><\/p>\n\n\n\n<!--more Continue Reading...-->\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Causes of the &#8216;Definer Does Not Exist&#8217; Error<\/strong><\/h3>\n\n\n\n<p>The &#8216;Definer Does Not Exist&#8217; error can emerge due to various scenarios:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Definer Deletion<\/strong>: If the user specified as the definer is removed from the MySQL system, the error arises.<\/li>\n\n\n\n<li><strong>Incomplete Migration<\/strong>: During database migration, if users are not fully transferred, the definer mismatch occurs.<\/li>\n\n\n\n<li><strong>Security Changes<\/strong>: Altering user privileges without considering dependent objects can trigger this error.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Creating procedure for test<\/h3>\n\n\n\n<p><br>We will create a simple procedure to return count from table &#8216;a&#8217; of database &#8216;test&#8217; and a specific user as a DEFINER.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">mysql&gt; grant all on test.* to 'spuser'@'localhost' identified by 'sppass';\nQuery OK, 0 rows affected (0.04 sec)\n\n<s>mysql&gt; flush privileges;\nQuery OK, 0 rows affected (0.04 sec)<\/s>\n<em>### Doc: If you modify the grant tables indirectly using account-management statements such as GRANT, REVOKE, SET PASSWORD, or RENAME USER, the server notices these changes and loads the grant tables into memory again immediately.\n<\/em>\n\nmysql&gt; DROP PROCEDURE IF EXISTS myproc;\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n\nmysql&gt; DELIMITER $\nmysql&gt; CREATE DEFINER='spuser'@'localhost' PROCEDURE myproc()\n    -&gt; BEGIN\n    -&gt;   select count(*) from test.a;\n    -&gt; END $\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql&gt; DELIMITER ;\n\nmysql&gt; select current_user();\n+----------------+\n| current_user() |\n+----------------+\n| root@localhost |\n+----------------+\n1 row in set (0.00 sec)\n\nmysql&gt; call test.myproc();\n+----------+\n| count(*) |\n+----------+\n|        6 |\n+----------+\n1 row in set (0.00 sec)\n\nQuery OK, 0 rows affected (0.00 sec)\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Introducing the definer error<\/h3>\n\n\n\n<p>Alright the procedure call above worked fine as expected. Now let&#8217;s create a trouble! Let&#8217;s drop a user and try to see what do we get here.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">mysql&gt; drop user 'spuser'@'localhost';\nQuery OK, 0 rows affected (0.00 sec)\n\n<s>mysql&gt; flush privileges;\nQuery OK, 0 rows affected (0.00 sec)<\/s>\n\nmysql&gt; call test.myproc();\nERROR 1449 (HY000): The user specified as a definer ('spuser'@'localhost') does not exist\n<\/pre>\n\n\n\n<p>Hmmm&#8230; This is the error I wanted to point &amp; explain. I encourage you to refer the DEFINER &amp; INVOKER in SQL SECURITY explained in my previous article and ofcourse MySQL documentation is a bible.<\/p>\n\n\n\n<p>Well so as the error says it is expecting a user which is not present. So the easy way out here is to create the dropped user, reload privileges and make a call.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Solution 1 &#8211; Create the missing user<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">mysql&gt; grant all privileges on test.* to 'spuser'@'localhost' identified by 'sppass';\nQuery OK, 0 rows affected (0.01 sec)\n\n<s>mysql&gt; flush privileges;\nQuery OK, 0 rows affected (0.00 sec)<\/s>\n\nmysql&gt; call test.myproc();\n+----------+\n| count(*) |\n+----------+\n|        6 |\n+----------+\n1 row in set (0.00 sec)\n\nQuery OK, 0 rows affected (0.00 sec)\n<\/pre>\n\n\n\n<p>Though we might not want to get into troubles at first! So how can we avoid from getting in to this situation?<\/p>\n\n\n\n<p>The answer is using &#8220;SQL SECURITY&#8221; defined as &#8220;INVOKER&#8221;. SQL SECURITY here defines that the procedure will run under the INVOKER&#8217;s privileges. (Default is DEFINER)<br>Specifying INVOKER we are free from the dependency of DEFINER user.<\/p>\n\n\n\n<p>Let&#8217;s test as follows:<br>&#8211; Create procedure with SQL SECURITY specified as INVOKER.<br>&#8211; Drop definer user<br>&#8211; call the procedure and&#8230;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Solution 2 &#8211; Use SQL SECURITY INVOKER<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">mysql&gt; DROP PROCEDURE IF EXISTS myproc;\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql&gt; DELIMITER $\nmysql&gt; CREATE DEFINER='spuser'@'localhost' PROCEDURE myproc()\n    -&gt; SQL SECURITY INVOKER\n    -&gt; BEGIN\n    -&gt;   select count(*) from test.a;\n    -&gt; END $\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql&gt; DELIMITER ;\nmysql&gt; drop user 'spuser'@'localhost';\nQuery OK, 0 rows affected (0.00 sec)\n\n<s>mysql&gt; flush privileges;\nQuery OK, 0 rows affected (0.01 sec)<\/s>\n\nmysql&gt; call test.myproc();\n+----------+\n| count(*) |\n+----------+\n|        6 |\n+----------+\n1 row in set (0.00 sec)\n\nQuery OK, 0 rows affected (0.00 sec)\n<\/pre>\n\n\n\n<p>Hmmm so this look good! No error &amp; stored procedure works well&#8230;even if we lost the user who created the procedure!<br>But there is an obvious understanding that the SQL SECURITY INVOKER clause may behave differently depending on privileges of the user who calls it.<\/p>\n\n\n\n<p>Alright, finally I&#8217;ll add one more way to resolve the error: &#8220;MySQL error 1449: The user specified as a definer does not exist&#8221;<br>The stored procedure or say MySQL routines are stored in mysql.proc table which also reflects in information_schema.ROUTINES table.<br>One can directly update the mysql.proc table&#8217;s DEFINER column to replace deleted user with existing user. Let&#8217;s do that.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Solution 3 &#8211; change DEFINER user<\/h3>\n\n\n\n<pre class=\"wp-block-preformatted\">mysql&gt; DROP PROCEDURE IF EXISTS myproc;\nQuery OK, 0 rows affected, 1 warning (0.00 sec)\n\nmysql&gt; DELIMITER $\nmysql&gt; CREATE DEFINER='spuser'@'localhost' PROCEDURE myproc()\n    -&gt; BEGIN\n    -&gt;   select count(*) from test.a;\n    -&gt; END $\nQuery OK, 0 rows affected (0.00 sec)\n\nmysql&gt; DELIMITER ;\n\nmysql&gt; select * from mysql.proc where name='myproc';\n+------+------+-----------+---------------+----------+-----------------+------------------+---------------+------------+---------+------------------------------------------+------------------+---------------------+---------------------+----------+---------+----------------------+----------------------+-------------------+------------------------------------------+\n| db   | name | type      | specific_name | language | sql_data_access | is_deterministic | security_type | param_list | returns | body                                     | definer          | created             | modified            | sql_mode | comment | character_set_client | collation_connection | db_collation      | body_utf8                                |\n+------+------+-----------+---------------+----------+-----------------+------------------+---------------+------------+---------+------------------------------------------+------------------+---------------------+---------------------+----------+---------+----------------------+----------------------+-------------------+------------------------------------------+\n| test | myproc | PROCEDURE | myproc        | SQL      | CONTAINS_SQL    | NO               | DEFINER       |            |         | BEGIN\n  select count(*) from test.a;\nEND | spuser@localhost | 2015-03-20 23:57:53 | 2015-03-20 23:57:53 |          |         | utf8                 | utf8_general_ci      | latin1_swedish_ci | BEGIN\n  select count(*) from test.a;\nEND |\n+------+------+-----------+---------------+----------+-----------------+------------------+---------------+------------+---------+------------------------------------------+------------------+---------------------+---------------------+----------+---------+----------------------+----------------------+-------------------+------------------------------------------+\n1 row in set (0.00 sec)\n\nmysql&gt; drop user 'spuser'@'localhost';\nQuery OK, 0 rows affected (0.00 sec)\n\n<s>mysql&gt; flush privileges;\nQuery OK, 0 rows affected (0.00 sec)<\/s>\n\nmysql&gt; call test.myproc();\nERROR 1449 (HY000): The user specified as a definer ('spuser'@'localhost') does not exist\n\nmysql&gt; update mysql.proc set  definer='root@localhost' where name='test';\nQuery OK, 1 row affected (0.00 sec)\nRows matched: 1  Changed: 1  Warnings: 0\n\nmysql&gt; select * from routines where routine_name='myproc';\n+---------------+-----------------+----------------+--------------+--------------+-----------+--------------------------+------------------------+-------------------+---------------+--------------------+----------------+----------------+--------------+------------------------------------------+---------------+-------------------+-----------------+------------------+-----------------+----------+---------------+---------------------+---------------------+----------+-----------------+----------------+----------------------+----------------------+--------------------+\n| SPECIFIC_NAME | ROUTINE_CATALOG | ROUTINE_SCHEMA | ROUTINE_NAME | ROUTINE_TYPE | DATA_TYPE | CHARACTER_MAXIMUM_LENGTH | CHARACTER_OCTET_LENGTH | NUMERIC_PRECISION | NUMERIC_SCALE | CHARACTER_SET_NAME | COLLATION_NAME | DTD_IDENTIFIER | ROUTINE_BODY | ROUTINE_DEFINITION                       | EXTERNAL_NAME | EXTERNAL_LANGUAGE | PARAMETER_STYLE | IS_DETERMINISTIC | SQL_DATA_ACCESS | SQL_PATH | SECURITY_TYPE | CREATED             | LAST_ALTERED        | SQL_MODE | ROUTINE_COMMENT | DEFINER        | CHARACTER_SET_CLIENT | COLLATION_CONNECTION | DATABASE_COLLATION |\n+---------------+-----------------+----------------+--------------+--------------+-----------+--------------------------+------------------------+-------------------+---------------+--------------------+----------------+----------------+--------------+------------------------------------------+---------------+-------------------+-----------------+------------------+-----------------+----------+---------------+---------------------+---------------------+----------+-----------------+----------------+----------------------+----------------------+--------------------+\n| myproc          | def             | test           | myproc         | PROCEDURE    |           |                     NULL |                   NULL |              NULL |          NULL | NULL               | NULL           | NULL           | SQL          | BEGIN\n  select count(*) from test.a;\nEND | NULL          | NULL              | SQL             | NO               | CONTAINS SQL    | NULL     | DEFINER       | 2015-03-20 23:58:51 | 2015-03-20 23:57:53 |          |                 | root@localhost | utf8                 | utf8_general_ci      | latin1_swedish_ci  |\n+---------------+-----------------+----------------+--------------+--------------+-----------+--------------------------+------------------------+-------------------+---------------+--------------------+----------------+----------------+--------------+------------------------------------------+---------------+-------------------+-----------------+------------------+-----------------+----------+---------------+---------------------+---------------------+----------+-----------------+----------------+----------------------+----------------------+--------------------+\n1 row in set (0.02 sec)\n\nmysql&gt; exit\nBye\nroot@ubuntu:~# mysql -uroot -pkedar\nWelcome to the MySQL monitor.  Commands end with ; or \\g.\nYour MySQL connection id is 5\nServer version: 5.5.30-log MySQL Community Server (GPL)\n\nCopyright (c) 2000, 2013, Oracle and\/or its affiliates. All rights reserved.\n\nOracle is a registered trademark of Oracle Corporation and\/or its\naffiliates. Other names may be trademarks of their respective\nowners.\n\nType 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.\n\nmysql&gt; use test\nReading table information for completion of table and column names\nYou can turn off this feature to get a quicker startup with -A\n\nDatabase changed\nmysql&gt; call test.myproc();\n+----------+\n| count(*) |\n+----------+\n|        6 |\n+----------+\n1 row in set (0.00 sec)\n\nQuery OK, 0 rows affected (0.00 sec)\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>The error &#8220;Definer does not exist&#8221; can be resolved by atleast 3 ways:<br>&#8211; Create the DEFINER (user).<br>&#8211; Change the DEFINER by updating mysql.proc.<br>&#8211; Bring in the INVOKER (with caution).<\/p>\n\n\n\n<p>Well as such we updated DEFINER column in mysql.proc table to avoid user creation.<br>Do you see a possibility of 4th solution to update security_type column of mysql.proc to INVOKER? See if that works! \ud83d\ude42<\/p>\n\n\n\n<p>Let me know.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<p>1. http:\/\/dev.mysql.com\/doc\/refman\/5.0\/en\/stored-programs-security.html<br>2. <a href=\"http:\/\/kedar.nitty-witty.com\/access-control-in-mysql-stored-routines-by-example-definer-invoker-sql-security\" target=\"_blank\" rel=\"noopener\" title=\"\">http:\/\/kedar.nitty-witty.com\/access-control-in-mysql-stored-routines-by-example-definer-invoker-sql-security<\/a><\/p>\n\n\n\n<p><strong>Update:<\/strong><br>Why &#8220;flush tables&#8221; commands are &#8220;strikethrough-ed&#8221; &#8211;&gt; because they&#8217;re not required.<\/p>\n","protected":false},"excerpt":{"rendered":"Explaining and providing solutions of MySQL error 1449: The user specified as a definer does not exist using SQL SECURITY INVOKER and DEFINER.\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[8,377],"tags":[300,397,396,301,427,671,336,302,108],"class_list":{"0":"post-2157","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-mysql","7":"category-mysql-articles","8":"tag-definer","9":"tag-definer-does-not-exist","10":"tag-error-1449","11":"tag-invoker","12":"tag-mysql","13":"tag-mysql-definer-does-not-exist","14":"tag-routine","15":"tag-sql-security","16":"tag-stored-procedure"},"aioseo_notices":[],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/posts\/2157","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/comments?post=2157"}],"version-history":[{"count":18,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/posts\/2157\/revisions"}],"predecessor-version":[{"id":3082,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/posts\/2157\/revisions\/3082"}],"wp:attachment":[{"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/media?parent=2157"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/categories?post=2157"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kedar.nitty-witty.com\/blog\/wp-json\/wp\/v2\/tags?post=2157"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}