Fixing error: cannot read property “values” from undefined

Typeerror: cannot read property “values” from undefined is one of the most persistent and frequent errors you can get when doing any type of scripting in Google Apps Script. One of the most frequent questions I get on this blog, so I decided to dedicate a post to helping people troubleshoot this pesky error.

First, we’ll talk about what this error means, then we’ll look at the two most common scenarios in which you might get this error, and finally, we’ll talk about what we can do to fix it.

What does typeerror: cannot read property “values” from undefined really mean?

To understand this, you first need to understand what it means to be undefined in JavaScript. Let’s take a look at a simple example using variables:

// This line is a variable declaration
// we create it, but do not assign it a value 
// so it is undefined

var a; 

// In this line we declare and assign a variable
// this is not undefined 

var b = 6;

Something is undefined in JavaScript when it is an object that is expected to hold a reference to a value, but in fact references nothing. There is a really good explanation at W3 schools on undefined in JS that is worth a look if you want some better examples.

In the context of our error message, it says we are trying to read a set of properties called “values” from something that is undefined, likely with a line that looks something like this if you are using the resources on this site:

var email = e.values[4];

When the script runs, it gets to this line or a line like it and and says “Ok, I see you want to create a variable called email, and you want this variable to equal the 5th value of something called e (our form submission event), but wait a minute, e is undefined! There is nothing there! Error!”

The event parameter (e) exists because we injected it into the script, but it doesn’t equal anything, so in turn we can’t access any of its properties. In the case of most Google Apps Scripts projects, this occurs because there is not event (e) passed in when you run the script in the debugger.

What Can I Do to Fix This in Google Apps Script? 

For most people, this is a quick fix: Submit a test form. DO NOT TRY TO RUN IN DEBUGGER. 

Remember the script needs an event, meaning we have to give it one. Since we’ve set a trigger tied to a form submission, that is the type of event that it expects.

 

 

 

I'm working on building the most comprehensive course available on building workflows with Google Apps Script.

Join the Course Waiting List for a Huge Discount!

* indicates required

18 thoughts on “Fixing error: cannot read property “values” from undefined”

  1. Arthur says:

    Hello,
    I have a problem with my forms I have this error but I send a test form but I have the same problem. Can you help me ?

    1. admin says:

      Can you post your code for me to look at?

      1. Curt Painter says:

        I am curious if there was a solution. I am having the same problem as Arthur. I have pasted my code below:

        function lunchDetention(e)
        {
        var studentName = e.values[4];
        var detentionDate = e.values[3];

        startDate = new Date(detentionDate);
        endDate = new Date( detentionDate);

        var startDate = new Date( );

        var myCal = CalendarApp.getDefaultCalendar( );

        myCal.createAllDayEvent(studentName,detentionDate);

        }

        1. BrownBearWhatDoYouSee says:

          First, make sure you are testing this by submitting a test form. Can you confirm you are doing that?

          This issue usually indicates an issue with a typo in the function, or a mis-referenced spreadsheet cell. Are you sure that the values (e.values[4] and e.values[3]) are correct using zero indexing, meaning the first column of the spreadsheet (usually the timestamp) is e.values[0]?

          If it’s not that, there are other things you can try as well.

  2. Lounhass says:

    Hello

    same goes for me.

    I copied and pasted your script but I keep getting the error message even though I added the correct values

    Please help me!

  3. ITGuide says:

    Hi Jeff,

    I’m liking this blog on Google App Scripts!

    I suspect you may have the answer to this already but 1 way around this that I found handy is to use javascript “try” and “catch” block. This worked for me.

    https://stackoverflow.com/questions/17180141/how-do-you-pass-back-a-custom-error-message-from-google-apps-scripts

    All you have to do to ignore the error is to leave your error handling empty.

    try{
    // function code goes here;
    }catch(e){
    // igore error
    // or if you prefer display an error message here
    }

    1. BrownBearWhatDoYouSee says:

      Thanks for the link! You’re right that try/catch is a great paradigm for error handling and has tons of applications for making robust Google Apps. Thanks for reading!

  4. nicol biden says:

    This error occurs in Chrome Browser when you read a property or call a method on an undefined object . Uncaught TypeError: Cannot read property of undefined error is probably easiest to understand from the perspective of undefined, since undefined is not considered an object type at all (but its own undefined type instead), and properties can only belong to objects within JavaScript. There are a few variations of this error depending on the property you are trying to access. Sometimes instead of undefined it will say null.

    http://net-informations.com/js/iq/unerror.htm

    1. BrownBearWhatDoYouSee says:

      Thanks for the link to the helpful resource. JE

  5. OH Please help… I have tried every tip tool and resource I can find to fix the failed to run error.
    I had the undefined error in debugger. The try/catch fixed that just to check the code.
    But I still get a failed trigger and the template isn’t created when I submit test form after test form after test form.
    //here is my code:
    function CreateSOI(e) {
    //e.values is an array of form values
    var timestamp = e.values[0];
    var lastname = e.values[1];
    var firstname = e.values[2];
    var grade = e.values[3];
    var age = e.values[4];
    var dateadmin = e.values[5];
    var cfu = e.values[6];
    var cfc = e.values[7];
    var mfu = e.values[8];
    var efu = e.values[9];
    var efc = e.values[10];
    var cfs = e.values[11];
    var cft = e.values[12];
    var nfu = e.values[13];
    var dfu = e.values[14];
    var css = e.values[15];
    var msuv = e.values[16];
    var mssv = e.values[17];
    var msua = e.values[18];
    var mssa = e.values[19];
    var msi = e.values[20];
    var esc = e.values[21];
    var ess = e.values[22];
    var nss = e.values[23];
    var nst = e.values[24];
    var nsi = e.values[25];
    var dsr = e.values[26];
    var csr = e.values[27];
    var cmu = e.values[28];
    var cmum = e.values[29];
    var cmr = e.values[30];
    var cms = e.values[31];
    var dmu = e.values[32];
    var mmi = e.values[33];
    var figural = e.values[34];
    var symbolic = e.values[35];
    var semantic = e.values[36];
    var creativity = e.values[37];
    var memory = e.values[38];
    var evaluation = e.values[39];
    var formversion = e.values[40];

    //file is the template file, and you get it by ID
    var file = DocumentApp.getFileById(‘1DcJvrFF_8sZQgL3hc1J4GdJ9spTfDNGo6QG642HGgq4′);

    //We can make a copy of the template, name it, and optionally tell it what folder to live in
    //file.makeCopy will return a Google Drive file object
    var folder = DriveApp.getFolderById(’17tih1cwh7gZI3yVV6g8UFPbb5SWxIUUH’)
    var copy = file.makeCopy(lastname + ‘.’ + firstname + ‘SOIclusterFormCR’, folder);

    //Once we’ve got the new file created, we need to open it as a document by using its ID
    var doc = DocumentApp.openById(copy.getId());

    //Since everything we need to change is in the body, we need to get that
    var body = doc.getBody();

    //Then we call all of our replaceText methods
    body.replaceText(‘<>’, timestamp);
    body.replaceText(‘<>’, lastname);
    body.replaceText(‘<>’, firstname);
    body.replaceText(‘<>’, grade);
    body.replaceText(‘<>’, age);
    body.replaceText(‘<>’, dateadmin);
    body.replaceText(‘<>’, cfu);
    body.replaceText(‘<>’, cfc);
    body.replaceText(‘<>’, mfu);
    body.replaceText(‘<>’, efu);
    body.replaceText(‘<>’, efc);
    body.replaceText(‘<>’, cfs);
    body.replaceText(‘<>’, cft);
    body.replaceText(‘<>’, nfu);
    body.replaceText(‘<>’, dfu);
    body.replaceText(‘<>’, css);
    body.replaceText(‘<>’, msuv);
    body.replaceText(‘<>’, mssv);
    body.replaceText(‘<>’, msua);
    body.replaceText(‘<>’, mssa);
    body.replaceText(‘<>’, msi);
    body.replaceText(‘<>’, esc);
    body.replaceText(‘<>’, ess);
    body.replaceText(‘<>’, nss);
    body.replaceText(‘<>’, nst);
    body.replaceText(‘<>’, nsi);
    body.replaceText(‘<>’, dsr);
    body.replaceText(‘<>’, csr);
    body.replaceText(‘<>’, cmu);
    body.replaceText(‘<>’, cmum);
    body.replaceText(‘<>’, cmr);
    body.replaceText(‘<>’, cms);
    body.replaceText(‘<>’, dmu);
    body.replaceText(‘<>’, mmi);
    body.replaceText(‘<>’, figural);
    body.replaceText(‘<>’, symbolic);
    body.replaceText(‘<>’, semantic);
    body.replaceText(‘<>’, creativity);
    body.replaceText(‘<>’, memory);
    body.replaceText(‘<>’, evaluation);

    //Lastly we save and close the document to persist our changes
    doc.saveAndClose();

    }

  6. I GOT IT …. OMG I GOT IT!!! Super Proud of myself!

    The error issue was that I had previously tried to run autocrat add on to achieve same end result and while I had deleted its components it was still causing issues with my new script. The autocrat not being reliable is the whole reason I chose to find and write the script instead.

    THANK YOU for this!

    I am now taking it a step further to generate 4 documents perform submit all with the same data.

    1. BrownBearWhatDoYouSee says:

      Awesome! I’m glad you got everything figured out. Thanks for reading, and be sure to post back if you hit anymore road blocks.

      JE

  7. Hazel says:

    Hi! Thanks for much for posting! I am filtering my form responses into various tabs based on Col2. I’d like for all responses from each tab to populate a doc in a folder for that tab.

    1. Should I be filtering in the responses sheet like I currently am or would it be better to write a filter into the function? If so how?

    2. If filtering first is best, how do I define which tab the values come from?

    1. BrownBearWhatDoYouSee says:

      I’m not sure what you mean by filtering here. Can you post an example of some code?

      Thanks for reading,
      Jeff

  8. Allison says:

    I’m using your code:
    function myFunction(e) {
    //e.values is an array of form values
    var timestamp = e.values[0];

    The trigger I’m using is On Edit because I want a doc to populate when I paste data into the spreadsheet rather than when a form is filled out. When I complete the event (e) by pasting new data into the spreadsheet, I’m notified that e is undefined: “TypeError: Cannot read property “0” from undefined. (line 3, file “Code”)”

    Can you help?

    1. BrownBearWhatDoYouSee says:

      Hi Allison,

      Thanks for reaching out. I’ve never really used the onEdit trigger, so the issue is likely about the shape of the event parameter that gets passed into myFunction, the variable we reference as e throughout the rest of the script. It seems like ‘e’ is likely defined, but since it is not a form submission, it does not have a values property, so e.values is undefined. My recommendation would be to log out the value of e using Logger.log(e) to see what is available to you on the edit functionality event. The logs are in the View > Logs menu item in the apps script editor.

      After you figure that out, you’ll likely have to change the way you are accessing the data. Feel free to post back here if you have any questions after logging the value of e.

      Thanks for reading,
      Jeff

  9. farah says:

    Thank you so much for your post. I am an absolute novice with a medical background but I tried my hand. Wanted a new letter to be created using a template named after the patient name and triggered whenever a new form was submitted. But it doesnt seem to do it. I have tried submitted a test form but error.

    please help. 🙁

    function myFunction(e) {
    var nameofPatient = e.values[1];
    var icNumber = e.values[2];
    var dateSeenInClinic = e.values[3];
    var dateOfSurgery = e.values [4];
    var surgeryPerformed = e.values [5];
    var costOfSurgery = e.values [6];
    var referralFee = e.values [7];
    var referredFrom = e.values [8];
    var file = DriveApp.getFileById(‘ReferralReply’);
    var folder = DriveApp.getFolderById(‘PremierClinic’);
    var copy = file.makeCopy(nameofPatient, folder);
    var doc = DocumentApp.openById(copy.getId());
    var body = doc.getBody();

    body.replaceText(‘{{Name of Patient}}’, nameofPatient);
    body.replaceText(‘{{Ic Number}}’, icnumber);
    body.replaceText(‘{{Date Seen In Clinic}}’, dateseeninClinic);
    body.replaceText(‘{{Date of Surgery}}’,dateofSurgery);
    body.replaceText(‘{{Surgery Performed}}’,surgeryperformed);
    body.replaceText(‘{{Cost of Surgery}}’,costofsurgery);
    body.replaceText(‘{{Referral Fee}}’,referralfee);
    body.replaceText(‘{{Referred From}}’,referredfrom);

    doc.saveAndClose();

    }

    1. BrownBearWhatDoYouSee says:

      Hi Farah,

      The first thing I see is that you are calling both DriveApp.getFileById and DriveApp.getFolderById using the names of the files/folders instead of the id. The ID is in the URL browser bar and is a long string of numbers and characters. There should also be methods like DriveApp.getFolderById available, but I like to get things by their unique id. I’d suggest starting there, which should give you some more additional error messages.

      JE

Leave a Reply

Your email address will not be published. Required fields are marked *