ORA-03120: two-task conversion routine: integer overflow

Toad for Oracle Base Edition (64-bit)
25.1.20.5192
Oracle Client : 23.7.0.25.01

If I have DBMS_Output enabled on the "DBMS_OUTPUT" tab I intermittently get ORA-03120: two-task conversion routine: integer overflow, errors when calling code which might be outputting dbms_output.put_lines. For some anonymous blocks, it will happen at the same point every time.

Observations:

  1. If I run in SQL*Plus with server output on, I don't see the error
  2. If I run in SQL*Developer, I don't see the error
  3. In TOAD on the DBMS_OUTPUT tab:
    a) If I have output enabled and Run a block, I see this issue intermittently
    b) If I have output disabled and Run a block, I don't see this issue
    c) If I run via Execute as Script, with set serveroutput on, I don't see this issue and DBMS_OUTPUT tab also displays output correctly

This points to an issue with the DBMS_OUTPUT tab in Toad and prevents me from debugging using dbms_output, which I use a lot.

Hi Paul,

A few have reported this but I haven't been able to reproduce it. I think it has to do with what is actually outputted (number/length of lines, maybe something else)

Can you send me the output you were expecting when the error occurred?

Also, as a workaround, put this in Toad.ini.

Under [SETTINGS], add this line: FetchDBMSOutputByLob=0

Hi John
I've just noticed that it seems to always occur after it writes the 10th line.

This does it:

begin
  for n in 1..10
  loop
    dbms_output.put_line(n);
  end loop;
end;

Unfortunately, that pl/sql block works for me w/o any problem.

Hi John

As is often the case, sigh. I have many instances with a range of Oracle versions and at the moment it seems to be happening on one particular on Oracle Database 19c Standard Edition 2, 19.25.0.0.0 on AWS, regardless of schema on that instance.

I have another 19.25 AWS instance and it doesn't happen. The problem is, the one it's happening on is our Dev instance, so it's crippling development at the moment.

Tried FetchDBMSOutputByLob=0, even restarted Toad, still happens.

Hi John

An update, I had changed FetchDBMSOutputByLob=0, whilst Toad was open and it seemed to remove it when I closed Toad. So I set it whilst Toad was closed and the error is currently not happening :crossed_fingers:.

Yeah, I forgot to mention, you should only attempt to change Toad.ini settings while Toad is not running. Toad reads that file into memory when it starts up, and writes to it occasionally (including on shutdown)

I just spoke to a colleague and he seems to think he fixed it on his dev schema by unticking "Trim Whitespace":

I have that ticked in my settings.

Interesting. I have that setting checked too, but couldn't reproduce it with your pl/sql block.

Can you take out the FetchDBMSOutputByLob setting and uncheck Trim Whitespace to see if the that setting really solves it?

For what it's worth, this is the PL/SQL block that I use to fetch DBMS Output when there are more than 10 lines of data returned using the line-by-line method. I started with the CLOB technique because users with lots of dbms output reported that the line-by-line method (which is what we used before, and which is what we use when FetchDBMSOutputByLob=0 is set) was too slow.

So, maybe someone smarter than me can find the problem in the pl/sql block below.


DECLARE
  v_lines   SYS.DBMS_OUTPUT.chararr;
  v_line    NVARCHAR2 (32767);
  v_clob    CLOB;
  v_cnt     NUMBER;
  v_output  NVARCHAR2 (32767);
BEGIN
  v_cnt := :inOutCnt;
  SYS.DBMS_OUTPUT.get_lines (v_lines, v_cnt);
  :inOutCnt := v_cnt;
  IF v_lines.COUNT > 0 THEN
    DBMS_LOB.createtemporary (v_clob, FALSE, DBMS_LOB.session);
    DBMS_LOB.open (v_clob, DBMS_LOB.lob_readwrite);
    v_output := NULL;
    FOR line IN 1 .. v_lines.COUNT
    LOOP
      v_line := regexp_replace(v_lines(line), '^[[:space:]]+|[[:space:]]+$');
      v_line := REPLACE(v_line, CHR (0));
      IF LENGTHB(v_output || v_line || CHR(13) || CHR(10)) > 32767 THEN
        DBMS_LOB.writeappend (v_clob, LENGTH(v_output), v_output);
        v_output := null;
      END IF;
      v_output := v_output || v_line || CHR (13) || CHR (10);
    END LOOP;
    if v_output is not null then
      DBMS_LOB.writeappend (v_clob, LENGTH(v_output), v_output);
    END IF;
    :outLines := v_clob;
    DBMS_LOB.freetemporary (v_clob);
  ELSE
    :outLines := null;
  END IF;
END;


SYS.DBMS_OUTPUT.chararr is defined as
type chararr is table of varchar2(32767) index by binary_integer;
Which could be UTF-8 character set and you are assigning to nvarchar2, which could UTF-16. I think v_line and v_output should be varchar2(32767)

I don't think you should do this
v_line := regexp_replace(v_lines(line), '^[[:space:]]+|[[:space:]]+);

as that will get rid of leading whitespace.
v_line := regexp_replace(v_lines(line), '[[:space:]]+$');
Is more correct.

Thanks Paul.

I have this comment in our source re: nvarchar2
// keep as NVARCHAR2 to account for multibyte chars

I think someone had arrows or somesuch. Maybe I should only use NVARCHAR2 on non-utf8 DBs. Also, it's interesting - if you just DBMS-outputted 10 lines, as in your pl/sql block, then my block really has no work to do other than to determine that there is nothing else to fetch. So I think the problem is in the call to SYS.DBMS_OUTPUT.get_lines (v_lines, v_cnt). The :inOutCnt param a few lines up is set to 1000.

The regex to remove leading and trailing is intentional. Right or wrong, the "trim whitespace" option removes leading and trailing. I'm not saying that can't change, but that's why it is the way it is.

Do you have any more info on that ORA-03120? Sometimes the error messages include "on line N in package BLAH".

Sorry, I read the whitespace trimming as end of line. I actually apply indentation to dbms_output sometimes, to help follow flow, so that explains why I lose that! It would be more useful as a dropdown (Trim all, Trim trailing, trim none) perhaps?

It's not safe to assign varchar2 (e.g. ANSI or UTF-8) to Nvarchar2 (always uses UTF-16). The codepoints don't match and it'll more than likely cause data corruption. Perhaps that is the source of the errors.

If you must concatenate, you need to use to_nchar(<your varchar2>)

DECLARE
  v_lines   SYS.DBMS_OUTPUT.chararr;
  v_line    NVARCHAR2 (32767);
  v_clob    CLOB;
  v_cnt     NUMBER;
  v_output  NVARCHAR2 (32767);
BEGIN
  v_cnt := :inOutCnt;
  SYS.DBMS_OUTPUT.get_lines (v_lines, v_cnt);
  :inOutCnt := v_cnt;

  IF v_lines.COUNT > 0 THEN
    DBMS_LOB.createtemporary (v_clob, FALSE, DBMS_LOB.session);
    DBMS_LOB.open (v_clob, DBMS_LOB.lob_readwrite);
    v_output := NULL;

    FOR line IN 1 .. v_lines.COUNT
    LOOP
      -- Convert the VARCHAR2 line to NVARCHAR2 before concatenating
      v_line := TO_NCHAR(regexp_replace(v_lines(line), '^[[:space:]]+|[[:space:]]+$'));
      v_line := REPLACE(v_line, CHR (0));  -- Only keep this if necessary
      
      -- Concatenate single-byte characters CHR(13) and CHR(10) as NVARCHAR2
      IF LENGTH(v_output || v_line || TO_NCHAR(CHR(13)) || TO_NCHAR(CHR(10))) > 32767 THEN
        -- Write to CLOB
        DBMS_LOB.writeappend (v_clob, LENGTH(v_output), v_output);  -- Use LENGTH for characters
        v_output := NULL;
      END IF;
      
      v_output := v_output || v_line || TO_NCHAR(CHR(13)) || TO_NCHAR(CHR(10));
    END LOOP;

    -- Handle remaining output
    IF v_output IS NOT NULL THEN
      DBMS_LOB.writeappend (v_clob, LENGTH(v_output), v_output);  -- Use LENGTH for characters
    END IF;

    :outLines := v_clob;
    DBMS_LOB.freetemporary (v_clob);
  ELSE
    :outLines := null;
  END IF;
END;

I'm not sure about chr(0) replacement?? But it might pay to declare nvarchar2(1) constants for chr(13) and chr(10)

Thanks Paul. I'll make these changes to see if it helps.

CHR(0) is replaced because if it is present, nothing after it will be displayed in Toad.

Hi Paul.

Next beta:

  1. Uses VARCHAR2 instead of NVARCHAR2 (this seems better than trying to make NVARCHAR2 safe)
  2. Adds an option to Preserve, Trim, Trim Leading, or Trim Trailing whitespace
  3. Adds an option to use CLOBs to fetch dbms output (so you don't have to edit Toad.ini with FetchDBMSOutputByLob=0 if it is still broken, or if not using NVARCHAR2 causes problems for anyone)

Please let me know if I missed anything, and - if you can test the beta next week - if #1 above solves the ORA-03120.

1 Like

Thanks John, that's great, I'll let you know if it does.