I'm trying to build upon Daniel Peter's approach in his HyperBatch library to build a HyperQuery tool that will allow me to get better insight into some large tables we have without needing to export the whole table to do external analysis.


Unfortunately, I stalled out at a pretty early stage, as I'm having trouble getting any Javascript code to identify which classes extend an interface. That's because every single class is returning a null SymbolTable.


  • I simplified the AJAX as far as I could and still I get SymbolTable = null for every single ApexClass.
  • The below MVR works just fine in other sandbox environments, so it seems like the problem is specific to this sandbox.
  • The exact same query in the developer workbench returns a populated SymbolTable, so the problem does not appear to be my class(es) or profile.
  • The SymbolTable is null for every ApexClass record, even after I recompiled all classes.
  • If I run the query via Execute Anonymous, the SymbolTable is populated. I can pass that same session id into my AJAX call instead of what I get from the GETSESSIONID merge variable and the behavior remains unchanged.


Why might my SymbolTable values be null only when queried via Javascript?




<apex:page showHeader="false" sidebar="false">
        "use strict";
        var query = "SELECT Name, SymbolTable FROM ApexClass WHERE NamespacePrefix = null",
            url = "/services/data/v39.0/tooling/query/?q=" + encodeURIComponent(query),
            request = new XMLHttpRequest();

        request.open("GET", url, /*async*/ true);
        request.setRequestHeader("Authorization", "Bearer {!GETSESSIONID()}");
        request.onreadystatechange = function () {
            if (request.readyState === 0 || request.readyState === 4) {
                var i, records = JSON.parse(request.responseText).records;

                console.debug(records); // results show up
                for (i = 0; i < records.length; i++) {
                    if (records[i].SymbolTable) {
                        console.debug(records[i]); // nada

Console Log

Console Log






Execute Anonymous


String query = 'SELECT+Name,SymbolTable+FROM+ApexClass+WHERE+Name=\'HyperQuery\'';
String root = URL.getSalesforceBaseUrl().toExternalForm();
String endpoint = root + '/services/data/v39.0/tooling/query/?q=' + query;

HttpRequest request = new HttpRequest();
request.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());

Map<String, Object> response = (Map<String, Object>)
        new Http().send(request).getBody()
List<Object> records = (List<Object>)response.get('records');
Map<String, Object> result = (Map<String, Object>)records[0];
system.assertNotEquals(null, result.get('SymbolTable'));

Debug Excerpt

{constructors=({annotations=(), location={column=5, line=6}, modifiers=(private) ...

  • 1
    I hate to break this to you... but it works in my developer org. Whatever is going on is not JavaScript's fault, or even how you're calling the API. Something else is afoot, and will require more sleuthing. The only way I was able to simulate a null SymbolTable in my org was to create two classes, make one dependent upon the other, then delete the class that the other depended on.
    – sfdcfox
    Commented Apr 5, 2017 at 17:00
  • 1
    A few guesses. 1) The Session ID you got in Visualforce might not be sufficient to access the SymbolTable - Ref. 2) The ApexClass needed to be recompiled to populated the SymbolTable - Ref. Unlikely if it works from Workbench. 3) Something in the specific SymbolTable is running afoul of a serialization process. What does the raw request.responseText look like? Commented Apr 5, 2017 at 21:47
  • 1
    "If there is not a cached version of SymbolTable, it will be compiled in the background and the query might take longer than expected. The SymbolTable returned from ApexClass does not contain references; to retrieve a SymbolTable with references, use ApexClassMember." - Ref Commented Apr 5, 2017 at 21:58
  • @AdrianLarson So it appears to be specific to one sandbox and accessing the SymbolTable via Javascript. Really makes it sound like something that is coming back in the response is dropping the SymbolTable. Maybe a problem Header or Cookie on the request? I'd be looking closely at the request and response in the Network tab of the Chrome Developer tools. Commented Apr 5, 2017 at 23:01
  • @DanielBallinger Also an interesting hypothesis, but I'm sending exactly the same headers in both environments as well. I'll take a closer look using Chrome Developer tools though.
    – Adrian Larson
    Commented Apr 5, 2017 at 23:36


You must log in to answer this question.

Browse other questions tagged .