ORA-06556: The Pipe Is Empty, Cannot Fulfill the UNPACK_MESSAGE Request
ORA-06556 is an Oracle error that occurs when DBMS_PIPE.UNPACK_MESSAGE is called but the pipe buffer contains no message to unpack. This typically happens when DBMS_PIPE.RECEIVE_MESSAGE either was not called beforehand, timed out, or returned a non-zero status that was ignored. Understanding the correct call sequence of DBMS_PIPE is essential to avoiding this error in inter-process communication (IPC) scenarios.
Top 3 Causes
1. Calling UNPACK_MESSAGE Without Checking RECEIVE_MESSAGE Return Value
RECEIVE_MESSAGE returns 0 on success, 1 on timeout, and 3 on error. If you skip the return value check and call UNPACK_MESSAGE directly, Oracle throws ORA-06556 because the buffer is empty.
-- WRONG: No return value check
DECLARE
v_status INTEGER;
v_message VARCHAR2(4000);
BEGIN
v_status := DBMS_PIPE.RECEIVE_MESSAGE('MY_PIPE', 5);
-- Missing IF v_status = 0 check!
DBMS_PIPE.UNPACK_MESSAGE(v_message); -- ORA-06556 if pipe is empty
END;
/
-- CORRECT: Always validate return status
DECLARE
v_status INTEGER;
v_message VARCHAR2(4000);
BEGIN
v_status := DBMS_PIPE.RECEIVE_MESSAGE('MY_PIPE', 5);
IF v_status = 0 THEN
DBMS_PIPE.UNPACK_MESSAGE(v_message);
DBMS_OUTPUT.PUT_LINE('Message: ' || v_message);
ELSIF v_status = 1 THEN
DBMS_OUTPUT.PUT_LINE('Timeout: no message in pipe.');
ELSE
DBMS_OUTPUT.PUT_LINE('Error, status: ' || v_status);
END IF;
END;
/
2. Timeout Occurred Before Message Was Sent
In multi-session environments, the sender may be delayed. If RECEIVE_MESSAGE times out (returns 1) and the code proceeds to UNPACK_MESSAGE anyway, ORA-06556 is raised. Implementing a retry loop resolves this.
DECLARE
v_status INTEGER;
v_message VARCHAR2(4000);
v_retry INTEGER := 0;
v_max_retry INTEGER := 3;
BEGIN
LOOP
v_status := DBMS_PIPE.RECEIVE_MESSAGE('MY_PIPE', 5);
IF v_status = 0 THEN
DBMS_PIPE.UNPACK_MESSAGE(v_message);
DBMS_OUTPUT.PUT_LINE('Received: ' || v_message);
EXIT;
ELSIF v_status = 1 AND v_retry < v_max_retry THEN
v_retry := v_retry + 1;
DBMS_OUTPUT.PUT_LINE('Retry ' || v_retry || ' of ' || v_max_retry);
ELSE
DBMS_OUTPUT.PUT_LINE('Failed after retries or error occurred.');
EXIT;
END IF;
END LOOP;
END;
/
3. Sender Did Not Call PACK_MESSAGE Before SEND_MESSAGE
If the sender skips DBMS_PIPE.PACK_MESSAGE, an empty message may be sent or no message is placed in the pipe at all, leaving the receiver with nothing to unpack. Always pair PACK_MESSAGE with SEND_MESSAGE.
-- Sender side (correct pattern)
DECLARE
v_status INTEGER;
BEGIN
DBMS_PIPE.PACK_MESSAGE('Hello from sender!'); -- Must call before SEND
v_status := DBMS_PIPE.SEND_MESSAGE('MY_PIPE', 10);
IF v_status = 0 THEN
DBMS_OUTPUT.PUT_LINE('Message sent successfully.');
ELSE
DBMS_OUTPUT.PUT_LINE('Send failed, status: ' || v_status);
END IF;
END;
/
-- Check pipe status (requires DBA privilege)
SELECT name, items, size_used, size_limit
FROM v$db_pipes
WHERE name = 'MY_PIPE';
Quick Fix Solutions
-
Always check the return value of
RECEIVE_MESSAGEbefore callingUNPACK_MESSAGE. UseIF v_status = 0as a gate. - Implement retry logic with a maximum retry count and timeout to handle delayed senders gracefully.
-
Purge stale pipes if the pipe is in an unknown state using
DBMS_PIPE.PURGE('MY_PIPE'). - Verify pipe names match exactly on both sender and receiver sides — pipe names are case-sensitive.
Prevention Tips
-
Build a shared wrapper procedure around
DBMS_PIPEcalls that enforces return value validation, retry logic, and logging by default. This prevents junior developers from making the classic mistake of skipping the status check. -
Monitor pipe activity regularly using
V$DB_PIPES. Set up alerts when pipe item counts grow unexpectedly, indicating a consumer is not reading messages correctly, which could lead to buffer overflow or stale state errors down the line.
📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.
Top comments (0)