Coldfusion “Routines cannot be declared more than once”

application.cfccoldfusioncoldfusion-9

We have the following code in our Application.cfc:

<cffunction name="onError" returnType="void" output="false">
    <cfargument name="exception" required="true">
    <cfargument name="eventname" type="string" required="true">
    <cfset cfcatch = exception>
    <cfinclude template="standalone/errors/error.cfm">
</cffunction>

Within the error.cfm page we have this code (I didn't write it):

<cfscript>
        function GetCurrentURL() {
            var theURL = "http";
            if (cgi.https EQ "on" ) theURL = "#TheURL#s";
            theURL = theURL & "://#cgi.server_name#";
            if(cgi.server_port neq 80) theURL = theURL & ":#cgi.server_port#";
            theURL = theURL & "#cgi.path_info#";
            if(len(cgi.query_string)) theURL = theURL & "?#cgi.query_string#";
            return theURL;  
        }
</cfscript>

This is all part of a script that puts together bunches of details about the error and records it to the database.

When an error occurs, we receive the message "The routine GetCurrentURL has been declared twice in different templates." However, I have searched the entire codebase in several different ways and found "GetCurrentURL" used only twice, both times in error.cfm. The first time is the declaration, and the second is actual use. So I'm not sure why CF is saying "in different templates".

My next thought was that the problem is a recursive call, and that error.cfm is erroring and calling itself, so I attempted these two changes, either of which should have resolved the issue and unmasked the real error:

<cfif StructKeyExists(variables,"GetCurrentURL") IS "NO">
    <cfscript>
            function GetCurrentURL() {
                var theURL = "http";
                if (cgi.https EQ "on" ) theURL = "#TheURL#s";
                theURL = theURL & "://#cgi.server_name#";
                if(cgi.server_port neq 80) theURL = theURL & ":#cgi.server_port#";
                theURL = theURL & "#cgi.path_info#";
                if(len(cgi.query_string)) theURL = theURL & "?#cgi.query_string#";
                return theURL;  
            }
    </cfscript>
</cfif>

And:

<cfscript>
    if (!StructKeyExists(variables,"GetCurrentURL")) {
            function GetCurrentURL() {
                var theURL = "http";
                if (cgi.https EQ "on" ) theURL = "#TheURL#s";
                theURL = theURL & "://#cgi.server_name#";
                if(cgi.server_port neq 80) theURL = theURL & ":#cgi.server_port#";
                theURL = theURL & "#cgi.path_info#";
                if(len(cgi.query_string)) theURL = theURL & "?#cgi.query_string#";
                return theURL;  
            }
    }
</cfscript>

Neither worked. I also tried adding this to the page just before the function call:

<cfoutput>"#StructKeyExists(variables,"GetCurrentURL")#"</cfoutput>

It caused the word "YES" to be printed on screen. This indicates that the above should work, as clearly the contents of the if statement will evaluate to "YES", and thus the if statement will evaluate to false, and thus the function will not be declared, and thus I will retain my sanity. But for some reason this problem persists.

Any thoughts on what might be occuring or how to troubleshoot next? I'm stuck at this point.

Best Solution

ColdFusion still sees the function declaration when it compiles it into bytecode. You can use a cfinclude to include the function declaration:

<cfif StructKeyExists(variables,"GetCurrentURL") IS "NO">
<cfinclude template="udf.cfm" />
</cfif>

Then in the udf.cfm place your function declaration. That should work as you want and prevent CF from throwing the error.

Related Question