ColdFusion 2023 FileRead throwing a 500 error

250 views Asked by At

We have recently gone through the process of upgrading from CF11 to CF2023. On our development servers, everything seemed work as expected. However, after installing on our production server, we have found a weird issue.

The fileRead command in a cfc file, seems to read the file, but then a 500 error is thrown after the cfc has finished processing. The issue does not happen with any other command in any other cfc (that we have found yet). I can reproduce this issue on our production serve; but using the same test page in development (or test) the code works fine.

Our immediate workaround is to use cffile action="read". This seems to work fine in development and production.

Sample test code that works in development but not in production (the file is read, contents dumped per the code, but then the 500 error is overlayed on the file dump) - fileReadTest.cfc:

component {

    struct function getRules() {

        try {

        var _rules = fileRead('[path]/configuration.json');
            _rules = deserializeJSON(_rules);

        return _rules;

        } catch( any e) {
            cfdump( var = e);
        }
    }

    remote string function test() {
        try {

            var _r = getRules()
            cfdump(var = _r);

            return 'test'

         } catch( any e) {
            cfdump( var = e);
        }
    }

}

These test is being called (for testing purposes) via the url with method as a parameter:

https://ourdoman.edu/fileReadTest.cfc?method=test

I do have access to the coldfusion administrator pages. I have compared prod to dev via the Settings Summary page and everything seems in line. I do not have access to IIS, but I am assured that those settings match from server to server.

One thing to note is that our dev server cannot be accessed from outside our network. In other words, you have to be on campus to use dev.

In looking at the coldfusion-error.log, I can see a SEVERE: Servlet.service() for servlet [CFCServlet] in context with path [] threw exception which seems to coincide with when the 500 error is generated. Looking up that error seems to lead to an IIS issue but I don't see anything definitive that I could point our network administrator to review.

Any insight would be super helpful. While we can use cffile as the workaround, my concern is that this is a sign of a bigger configuration issue.

Thanks

Edit:

Slimmed down version of the code to reproduce the error:

component {
    string function getRules() {
        var _rules = fileRead('c:/applications/test/test.txt');
        
        return _rules;
    }

    remote string function test() {
        var _r = getRules();
        return _r;                
    }
}

test.txt = This is a test.

Results: File is read, data is cfdumped, and then the 500 error Results: File is read, data is cfdumped, and then the 500 error1

Update: As a test, I tried using fileRead to read a fileObject as returned by fileOpen. For example:

 var x = fileOpen('[path]/test.txt')
 var y = fileRead(x, 16);
         fileClose(x);

The result is the same. The file is read and outputted (see sample code above), but then the 500 error is displayed. If I take out the fileRead, the fileOpen and fileClose seem to work without issue.

Also, it was suggested to me that I look at the application.cfc onRequestStart / onRequestEnd. I can verify that those are executing normally - as a test, I had them send an email per start and end. Also, the onError in the application.cfc will send an email as well if an error where to occur.

Testing Update

In my test cfc, I created a loop to iterate over the function that calls the fileRead. Each iteration calls the fileRead successfully as indicated by the data being cfdumped. Once the iteration is completed, the 500 error is generated.

Response

I thought it might helpful to see what the console response looks like. For example if the file is "this is a test", the response looks like the following. First file content and then the 500 Error is appended to the response.

<wddxPacket version='1.0'>
    <header/>
    <data>
        <string>
            this is a test<char code='0d'/>
            <char code='0a'/>
        </string>
    </data>
</wddxPacket>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>500</title>
        <style>
            body { 
    ... 

A Clue?

An important clue (?): If the .cfc that does the fileRead is called from a .cfm, using cfhttp,createObject,invoke, it works with no error. But if called via [URL]/test.cfc?method=getData or (as the app was initially doing) via $http (AngularJS), the error is generated. Both of those methods are using the same URL. It also fails if called from another cfc.

Another tidbit FileWrite behaves the same way as FileRead. When called from a .cfc, it writes the file, but then throws the 500 Error.

Stack Trace

Jul 11, 2023 1:08:07 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [CFCServlet] in context with path [] threw exception
java.util.NoSuchElementException: No value present
    at java.base/java.util.Optional.get(Optional.java:143)
    at coldfusion.monitor.beans.RequestData.isGraphQlService(RequestData.java:795)
    at coldfusion.monitor.beans.RequestData.updateFunctionMetrics(RequestData.java:618)
    at coldfusion.monitor.beans.RequestData.updateTagData(RequestData.java:459)
    at coldfusion.monitor.beans.RequestData.updateData(RequestData.java:223)
    at coldfusion.monitor.event.RequestMonitorEventProcessor.onRequestEnd(RequestMonitorEventProcessor.java:419)
    at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:82)
    at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:47)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:492)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:373)
    at org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:459)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:926)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1791)
    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:833)
2

There are 2 answers

5
Michael Schmidt On

Your method signature says it is returning a string. However you aren't returning a string could this be the issue?

3
charlie arehart On

Given what's been said in the dozens of comments (or your original and the for-now-only other answer), I'd wonder what you if you try adding a returnformat querystring to the call of the CFC as a URL, to change the format of what's being returned. You could try https://ourdoman.edu/fileReadTest.cfc?method=test&returnformat=plain, for example, or returnformat=json.

As you may know, the default is for CF to return such results as wddx (which is xml). Maybe that's somehow leading to your problems. I can't fathom what that could be, but it could at least give you/us a clue. And if somehow either variant works better, you could also set the "correct" returnformat as an argument of the same name on the method definition. (I have a 2017 blog post on how to do that in a script-based function definition. And to be clear, I do see you define the test function's return type to be string, which is a separate matter.)

Either way, it will be interesting to hear if this helps at all.