Skip to main content
Participating Frequently
August 31, 2023
Question

QueryDeleteColumn errors out with java.lang.NegativeArraySizeException

  • August 31, 2023
  • 3 replies
  • 521 views

I need help with an error I can't find an explanation for anywhere.

 

On ColdFusion 2021, I'm trying to delete a column from a query. The query for sure contains the column I am trying to delete, as you can see from the code snippet, which works otherwise when I comment QueryDeleteColumn.

 

<cftry>
	<cfset local.newColumnArray = ArrayNew(1)>
	<cfloop query="Data">
		<cfif len(Data.columName)>
			<cfset ArrayAppend(local.newColumnArray, Data.columName)>
		<cfelse>
			<cfset ArrayAppend(local.newColumnArray, otherMethod(Data.differentColumn))>
		</cfif>
	</cfloop>
	<cfset QueryAddColumn(Data,"newColumn","VarChar", local.newColumnArray)>
	<cfset QueryDeleteColumn(Data,"columName")>
<cfcatch type="any">
		<cf_mcabort message="xxx [line #cfcatch.tagContext[1].line#]: #CFCATCH.Message#"  except="#cfcatch#">
</cfcatch>
</cftry>

 

However, when I try do include that call, I get the following error:

java.lang.NegativeArraySizeException: -1
at coldfusion.sql.QueryTableMetaData.deleteColumnNameAndType(QueryTableMetaData.java:539)
at coldfusion.sql.imq.imqTable.deleteColumnnNameAndType(imqTable.java:321)
at coldfusion.sql.QueryTable.deleteColumn(QueryTable.java:705)
at coldfusion.runtime.QueryFunction.QueryDeleteColumn(QueryFunction.java:1025)
at coldfusion.runtime.CFPage.QueryDeleteColumn(CFPage.java:2508)
at cfTransactions2ecfc627721595$funcLOOKUPTRANSACTION.runFunction(xxxxxx:68)
at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:623)
at coldfusion.filter.SilentFilter.invoke(SilentFilter.java:47)
at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:516)
at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:95)
at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:463)
at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:438)
at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:681)
at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:980)
at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:762)
at coldfusion.filter.ComponentFilter.invoke(ComponentFilter.java:261)
at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:606)
at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:43)
at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)
at coldfusion.filter.PathFilter.invoke(PathFilter.java:162)
at coldfusion.filter.LicenseFilter.invoke(LicenseFilter.java:30)
at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:97)
at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28)
at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38)
at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:60)
at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38)
at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22)
at coldfusion.xml.rpc.CFCServlet.invoke(CFCServlet.java:167)
at coldfusion.xml.rpc.CFCServlet.doGet(CFCServlet.java:318)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:311)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:46)
at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:47)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:377)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:889)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:829) 

 

My best guess is that this has to do with the query, as I use this method elsewhere with very similar code and it works fine. I've tried deleting different columns, including the one I dinamically add there, to no avail. I haven't figured out how, though.

    3 replies

    AlHolden
    Inspiring
    February 21, 2025

    It's been a year plus since the last reply, and I get the same error from an attempt to delete a column from a SP (sproc) generated cfprocresult set (Azure MS-SQL) in CF2021:

    <cfstoredproc procedure="Get_Centers" datasource="#application.datasource#" cachedwithin="#createTimespan(0,0,0,2)#">
    	<cfprocparam variable="IdClient" cfsqltype="CF_SQL_INTEGER" value="#val(struReturn.sessionStruct.client_id)#" />
    	<cfprocresult name="struReturn.data" />
    </cfstoredProc>
    <cfset queryDeleteColumn(struReturn.data,'SECRETCOL') /> <!--- NegativeArraySizeException ERROR --->

     

    My fix was a QoQ to "re-cast" the results as a query type - that CF apparently likes better:

     

    <cfstoredproc procedure="Get_Centers" datasource="#application.datasource#" cachedwithin="#createTimespan(0,0,0,2)#">
    	<cfprocparam variable="IdClient" cfsqltype="CF_SQL_INTEGER" value="#val(struReturn.sessionStruct.client_id)#" />
    	<cfprocresult name="qResults" />
    </cfstoredProc>
    <cfquery name="struReturn.data" dbtype="query">  <!--- DUMB BUT NEEDED --->
    	SELECT * FROM qResults
    </cfquery>
    <cfset queryDeleteColumn(struReturn.data,'SECRETCOL') /> <!--- WORKS --->

     

     

    Hope this helps someone.

    BKBK
    Community Expert
    Community Expert
    February 22, 2025

    @AlHolden , With the error message

     

    java.lang.NegativeArraySizeException

     

    ColdFusion may be trying to tell you something. Chances are that, unknown to you, the query object is being modified by some underlying process.

     

    For example, your code contains an existential issue. The query object qResults is cached for just 2 seconds. So the code assumes that the query-of-query runs within 2 seconds after the stored procedure. That is a pretty tight timespan, hence an unrealistic assumption.

     

    There might be circumstances where the assumption is not true. Think, for example, of network latency between ColdFusion and the database server. There is then this fundamental question:

    • Which query object does the query of query refer to: the cached query or a newly generated query?

    That makes me ask what the point is of such a shortly lived cache. 

     

    In any case, I have already suggested a neat way to avoid any such misunderstanding. Before deleting a query-column, first test whether it exists.

     

    In your case, the code will be something like

     

    <!---
    Suggestion: Raise 'cachedWithin' to a more realistic value (10 seconds, say), to ensure that the same object is reused.
    Test whether a column exists before deleting it. If it unexpectedly doesn't exist, then an underlying process might have modified the query. 
    --->
    <cfstoredproc procedure="Get_Centers" datasource="#application.datasource#" cachedwithin="#createTimespan(0,0,0,10)#">
    	<cfprocparam variable="IdClient" cfsqltype="CF_SQL_INTEGER" value="#val(struReturn.sessionStruct.client_id)#" />
    	<cfprocresult name="qResults" />
    </cfstoredProc>
    
    <cfif queryKeyExists(qResults, "SECRETCOL")>
    	<cfset queryDeleteColumn(qResults,"SECRETCOL")>
    <cfelse>
        <!--- An underlying process has probably modified the query. Investigate. --->
        <!--- Dump any errors in the logs folder --->
        <cftry>
         <cfdump var="#qResults#" format="html" output="#server.coldfusion.rootDir#\logs\qResultsQueryDump.html">
        <cfcatch type="any">
            <cfdump var="#cfcatch#" format="html" output="#server.coldfusion.rootDir#\logs\qResultsCfcatch.html">
        </cfcatch>
        </cftry>
    </cfif>

     

     

     

    AlHolden
    Inspiring
    February 22, 2025

    Wow, jumping in on a Satruday. Thanks @BKBK !

    Good catch, you are correct that the application of a cache appears to be the pivoting factor in this example's error.

    However, I'm not sure the time span of the cache is the issue. I've created a simplified standalone example which employs a full one day cache - and the error is still present, even when employing the "does it exist?" test first.

    Here is the "broken" version:

    <cfstoredproc procedure="Get_Centers" datasource="[redacted]" cachedwithin="#createTimespan(1,0,0,0)#">
    	<cfprocparam variable="IdClient" cfsqltype="CF_SQL_INTEGER" value="2" />
    	<cfprocresult name="qResults" />
    </cfstoredProc>
    
    <cfdump var="#qResults#" />
    <hr/>
    <cfdump var="#qResults.columnList#" />
    <hr/>
    <cfdump var="#queryKeyExists(qResults, "ADDED_IDUSERS")#" />
    <hr/>
    
    <cfif queryKeyExists(qResults, "ADDED_IDUSERS")>
    	<cfset queryDeleteColumn(qResults,'ADDED_IDUSERS') />
    </cfif>
    
    <hr/>
    <cfdump var="#qResults.columnList#" />

     Which produces this:

    Next, here is the "fixed" version:

    <cfstoredproc procedure="Get_Centers" datasource="[redacted]" cachedwithin="#createTimespan(1,0,0,0)#">
    	<cfprocparam variable="IdClient" cfsqltype="CF_SQL_INTEGER" value="2" />
    	<cfprocresult name="qResults" />
    </cfstoredProc>
    
    <!--- ADDED --->
    <cfquery name="qResults" dbtype="query">
    	SELECT * FROM qResults
    </cfquery>
    
    <cfdump var="#qResults#" />
    <hr/>
    <cfdump var="#qResults.columnList#" />
    <hr/>
    <cfdump var="#queryKeyExists(qResults, "ADDED_IDUSERS")#" />
    <hr/>
    
    <cfif queryKeyExists(qResults, "ADDED_IDUSERS")>
    	<cfset queryDeleteColumn(qResults,'ADDED_IDUSERS') />
    </cfif>
    
    <hr/>
    <cfdump var="#qResults.columnList#" />

    Here's the error-free result, after the ADDED interim step "turn this query into a query" step

    So to me, it seems a bit buggy.  The application of the cache seems to affect some internal column array, no matter how long the life span of the cache. The queryKeyExists function considers the column extant, while the queryDeleteColumn disagrees, perhaps using a different test.

    Can you audit my logic? Thanks again.

     

    BKBK
    Community Expert
    Community Expert
    March 24, 2024

    The query is an object, and you have been manipulating it. So, before calling queryDeleteColumn, you have to first test for the existence of the column:

     

    <cfif queryKeyExists(Data, "columName")>
    	<cfset queryDeleteColumn(Data,"columName")>
    </cfif>
    sharp_quirk16B6
    Inspiring
    March 11, 2024

    I received this exact same error message.  I am also using CF2021, fully patched.  Did you ever find a solution or workaround?

     

    In my case I am calling queryExecute() to run a SQL statement.  My T-SQL code utilizes OFFET-FETCH and CTEs to return the total number of records in a column named [totalCount].  From the CF side, this should be a basic query result.  I get the first value of [totalCount] and then try to delete that column before returning the results:

    local.data = queryExecute(sql=sql, params={ offset:arguments.offset, limit:arguments.limit })
    local.recordcount = local.data.totalCount
    queryDeleteColumn(local.data, "totalCount")