ERROR 1415 (0A000): Not allowed to return a result set from a trigger is raised when a trigger body executes a SELECT statement that would return rows directly to the client. The error symbol is ER_SP_NO_RETSET.
Impact
MySQL triggers execute automatically in response to INSERT, UPDATE, or DELETE events on a table. Unlike stored procedures, triggers are not invoked by client code that expects a result set — they fire as side effects within the statement that triggered them. Because of this, MySQL forbids any statement inside a trigger that would send rows back to the client connection.
When this error is raised, the triggering DML statement (INSERT, UPDATE, or DELETE) is aborted and rolled back. Any application that relies on that statement — an ORM performing a model save, a migration script inserting seed data, or an API endpoint updating a record — will receive this error and fail. The error surfaces at the moment the trigger fires, not at trigger creation time, so a problematic trigger can be deployed undetected and only fail when rows are actually modified.
Common Causes
A bare
SELECTinside a trigger body. A developer writes aSELECT ... FROM some_table WHERE ...directly in the trigger to look up a related value, not realizing that unassignedSELECTstatements in a trigger context send rows to the client.Calling a stored procedure from a trigger that itself contains a result-returning
SELECT. If the trigger callsCALL my_proc()andmy_prochas an unassignedSELECT, the rows propagate through the procedure call and violate the trigger restriction.Debugging
SELECTleft in trigger code. A developer adds aSELECT 'reached this point'orSELECT NEW.idfor debugging, then forgets to remove it before deploying.Using
SELECT ... INTOincorrectly. Forgetting theINTOclause when assigning a value to a variable, turning what should be a variable assignment into a result-returning query.
Troubleshooting and Resolution Steps
Inspect the trigger body to find the offending
SELECT:SHOW CREATE TRIGGER trigger_name\GOr query the information schema across all triggers on a table:
SELECT TRIGGER_NAME, ACTION_STATEMENT FROM information_schema.TRIGGERS WHERE EVENT_OBJECT_SCHEMA = 'your_db' AND EVENT_OBJECT_TABLE = 'your_table';Replace bare
SELECTwithSELECT ... INTOwhen reading a value into a variable. This is the most common fix — the result is captured in a variable instead of being returned to the client:-- Wrong: returns a result set CREATE TRIGGER after_order_insert AFTER INSERT ON orders FOR EACH ROW BEGIN SELECT discount_rate FROM pricing WHERE tier = NEW.tier; -- ERROR 1415 END; -- Correct: assign the value into a local variable CREATE TRIGGER after_order_insert AFTER INSERT ON orders FOR EACH ROW BEGIN DECLARE v_discount DECIMAL(5,2); SELECT discount_rate INTO v_discount FROM pricing WHERE tier = NEW.tier; -- use v_discount for further logic END;Remove debugging
SELECTstatements from the trigger body. Replace anySELECT 'debug message'lines with a no-op or delete them entirely, then recreate the trigger:DROP TRIGGER IF EXISTS trigger_name; -- recreate without the SELECT statementFix stored procedures called from the trigger. If the trigger calls a stored procedure, audit that procedure for unassigned
SELECTstatements:SHOW CREATE PROCEDURE procedure_name\GRewrite any result-returning
SELECTinside the procedure to useSELECT ... INTOvariables, or restructure so the procedure does not return result sets when called from a trigger context.Re-create the trigger after applying fixes. MySQL stores trigger definitions as-is, so
ALTER TRIGGERdoes not exist — you must drop and recreate:DROP TRIGGER IF EXISTS after_order_insert; DELIMITER $$ CREATE TRIGGER after_order_insert AFTER INSERT ON orders FOR EACH ROW BEGIN DECLARE v_discount DECIMAL(5,2); SELECT discount_rate INTO v_discount FROM pricing WHERE tier = NEW.tier; END$$ DELIMITER ;
Additional Information
- The SQLSTATE
0A000is the standard "feature not supported" class, indicating this is a categorical restriction in MySQL's execution model, not a configuration issue. - The same restriction applies to events (
CREATE EVENT) — a scheduled event body cannot contain a bareSELECTthat returns rows to a client either. SELECT ... INTO @user_variable(session variables) is also valid inside a trigger and avoids the error, in addition toSELECT ... INTO local_variable.- Stored procedures do not have this restriction by default — a
CALLfrom a client connection can return result sets from a procedure. The restriction is specific to triggers (and events) because they have no direct client caller to receive rows. - ORMs such as Hibernate, SQLAlchemy, and ActiveRecord typically surface this as a generic database execution error wrapping
ERROR 1415. Check the caused-by chain in the exception for the MySQL error code. - There is no MySQL configuration option to lift this restriction — it is inherent to the trigger execution model in all MySQL versions (5.x, 8.0, 8.4).
Frequently Asked Questions
Why can stored procedures return result sets but triggers cannot?
A stored procedure is called explicitly by a client (CALL proc()), so MySQL knows there is a client waiting to receive rows. A trigger fires implicitly as part of another statement — there is no separate client call context expecting rows from the trigger, so returning a result set is undefined and therefore prohibited.
Can I use SELECT ... INTO freely inside a trigger?
Yes. SELECT col INTO var FROM t WHERE ... assigns the result to a local declared variable or a session variable (@var) and does not send rows to the client. This is the standard way to read data inside a trigger and is fully supported.
The trigger was created without error, so why does MySQL only fail at runtime?
MySQL does not fully validate trigger bodies against all runtime restrictions at CREATE TRIGGER time. The check that a result set cannot be returned is enforced at execution time, when the trigger actually fires. This means the trigger can be created and deployed successfully, and the error only appears when a matching INSERT/UPDATE/DELETE occurs.
Can I call a stored procedure from a trigger if that procedure conditionally returns rows?
No. If the procedure contains any code path that could return a result set, and that path is taken at runtime, MySQL will raise error 1415. The safest approach is to ensure procedures that are called from triggers never contain bare SELECT statements — use SELECT ... INTO exclusively for any data retrieval inside them.