Airtable/airtable.js

TypeError: Cannot read property 'offset' of undefined

rubik opened this issue ยท 25 comments

rubik commented

It seems that if some cells are empty, the select() method fails with the following error:

TypeError: Cannot read property 'offset' of undefined
at /node_modules/airtable/lib/query.js:109:28
at /node_modules/airtable/lib/run_action.js:70:17

This prevents all the other records to be read, so it is a pretty impacting issue. The library should just keep the empty value as an empty string or null or undefined. I.e. anything that does not crash.

I'm not sure it's empty cells that cause the issue - I'm seeing this error and every cell of every record in my test table has a value.

Has anyone made any progress with this? I'm getting the error a lot. I do have some empty cells.

Ran into this as well - I think adding a check to see if result is defined on line 158 of query.ts could fix it. I haven't taken a deep dive into the code though so that might just be a band-aid fix for a larger issue

Experiencing this too currently. My code looks like this but I can't figure out what the error is -

ATBase("Items")
      .select({
        view: "Grid view"
      })
      .eachPage(
        function page(records, fetchNextPage) {
          records.forEach(function(record) {
            myArr.push({
              id: record.id,
              ...record._rawJson.fields
            });
          });
          fetchNextPage();
        },
        function done(err) {
          if (err) {
            console.error(err);
          } else {
            callback();
          }
        }
      );

Experiencing this too currently. My code looks like this but I can't figure out what the error is -

I got the same issue with airtable.js
Had to switch to axios (see curl tab in API) and then was able to retrieve data and assign in to global variables.

I've seen this recently. It's probably due to an error inside of the eachPage function.
Try wrapping that into a try/catch :

ATBase("Items")
      .select({
        view: "Grid view"
      })
      .eachPage(
        function page(records, fetchNextPage) {
         try {
          records.forEach(function(record) {
            myArr.push({
              id: record.id,
              ...record._rawJson.fields
            });
          });
          } catch(e){ console.log('error inside eachPage => ',e)}
          fetchNextPage();
        },
        function done(err) {
          if (err) {
            console.error(err);
          } else {
            callback();
          }
        }
      );

I've seen this recently. It's probably due to an error inside of the eachPage function.
Try wrapping that into a try/catch :

ATBase("Items")
      .select({
        view: "Grid view"
      })
      .eachPage(
        function page(records, fetchNextPage) {
         try {
          records.forEach(function(record) {
            myArr.push({
              id: record.id,
              ...record._rawJson.fields
            });
          });
          } catch(e){ console.log('error inside eachPage => ',e)}
          fetchNextPage();
        },
        function done(err) {
          if (err) {
            console.error(err);
          } else {
            callback();
          }
        }
      );

Thanks for the suggestion! I tried the try/catch wrapping but I'm still getting the same error unfortunately. It didn't fall into the catch block. My entire console error is from before is

Uncaught (in promise) TypeError: Cannot read property 'offset' of undefined
    at eval (query.js:109)
    at eval (run_action.js:70)

@dezignhero try moving the try catch inside the forEach loop to get a meaningful error message like so (untested).

ATBase("Items")
      .select({
        view: "Grid view"
      })
      .eachPage(
        function page(records, fetchNextPage) {
          records.forEach(function(record) {
           try {
            myArr.push({
              id: record.id,
              ...record._rawJson.fields
            });
          } catch(e){ console.log('error inside eachPage => ',e)}
          });
          fetchNextPage();
        },
        function done(err) {
          if (err) {
            console.error(err);
          } else {
            callback();
          }
        }
      );

Looking at your code, I'm assuming your issue is that you are calling record.id, but it should be record.getId().

I think that the meaningless error message thrown by airtable should be fixed though, this is bad practice.

Cheers!

I'm not sure why it led to this error, but I discovered I had not installed an NPM module I was requireing. Instead of node telling me this, it somehow came up from Airtable just as everyone else's here.

In case this helps anyone else.

@dezignhero try moving the try catch inside the forEach loop to get a meaningful error message like so (untested).

ATBase("Items")
      .select({
        view: "Grid view"
      })
      .eachPage(
        function page(records, fetchNextPage) {
          records.forEach(function(record) {
           try {
            myArr.push({
              id: record.id,
              ...record._rawJson.fields
            });
          } catch(e){ console.log('error inside eachPage => ',e)}
          });
          fetchNextPage();
        },
        function done(err) {
          if (err) {
            console.error(err);
          } else {
            callback();
          }
        }
      );

Looking at your code, I'm assuming your issue is that you are calling record.id, but it should be record.getId().

I think that the meaningless error message thrown by airtable should be fixed though, this is bad practice.

Cheers!

Thanks for the suggestions, I wrapped the try/catch inside the forEach as well as switched .id to .getId() but the offset issue still persists :(. The catch does not yield any new errors at all either.

ATBase("Items")
      .select({
        view: "Grid view"
      })
      .eachPage(
        function page(records, fetchNextPage) {
          records.forEach(function(record) {
            try {
              myArr.push({
                id: record.getId(),
                ...record._rawJson.fields
              });
            } catch (e) {
              console.log(e);
            }
          });
          fetchNextPage();
        },
        function done(err) {
          if (err) {
            console.error(err);
          } else {
            dispatch("setItems", myArr);
          }
        }
      );

I also had this error when following the auto-generated documentation:

base('my base').select({
    // Selecting the first 3 records in Master list:
    maxRecords: 3,
    view: 'my view'
})

The error went away when I changed maxRecords to pageSize:

base('my base').select({
    pageSize: 10,
    view: 'my view'
})

I've only been using airtable for 10 minutes so I can't offer anything more insightful, but this is what worked for me.

I also had this error when following the auto-generated documentation:

base('my base').select({
    // Selecting the first 3 records in Master list:
    maxRecords: 3,
    view: 'my view'
})

The error went away when I changed maxRecords to pageSize:

base('my base').select({
    pageSize: 10,
    view: 'my view'
})

I've only been using airtable for 10 minutes so I can't offer anything more insightful, but this is what worked for me.

Thanks! I tried this but error still persists :(

@dezignhero Since this error message is a kind of catch-all, I think we'll need to isolate which line/character of your code specifically is making it happen or not happen. That's how I ended up finding mine.

I'd be curious to know if you start stripping out a bunch of your code and making it do simple things like console.log("hello") if it stops giving you the error.

If the error does stop, at what point when you start reintroducing bits does it complain?

For example...

ATBase("Items")
      .select({
        view: "Grid view"
      })
      .eachPage(
        function page(records, fetchNextPage) {
          /* records.forEach(function(record) {
            try {
              myArr.push({
                id: record.getId(),
                ...record._rawJson.fields
              });
            } catch (e) {
              console.log(e);
            }
          }); */
          console.log("hello");
          fetchNextPage();
        },
        function done(err) {
          if (err) {
            console.error(err);
          } else {
            // dispatch("setItems", myArr);
            console.log("done");
          }
        }
      );

Hello! You guys! This happens because the page tries to fetch the next nonexistent page, fix by:

          Base('Training Booked')
            .select({

                fields : ['Type of Training', 'Date & Time of Host'],
                filterByFormula :`AND(NOT(Confirmed), Token = '${Token}')`,


            }).eachPage( function page(records, next) {

                    records.forEach(function(rec) {

                        try {

                            ToReturn.push(rec)

                        } catch (err) {

                            console.error(err);

                        }

                    })

                    try { // HERE

                        next();

                    } catch { return; }

            }, function (err) {
                if (err) {

                    console.error(err);

                    rej(err.statusCode);
                    return;

                }

                acpt(ToReturn);

Hello! You guys! This happens because the page tries to fetch the next nonexistent page, fix by:

          Base('Training Booked')
            .select({

                fields : ['Type of Training', 'Date & Time of Host'],
                filterByFormula :`AND(NOT(Confirmed), Token = '${Token}')`,


            }).eachPage( function page(records, next) {

                    records.forEach(function(rec) {

                        try {

                            ToReturn.push(rec)

                        } catch (err) {

                            console.error(err);

                        }

                    })

                    try { // HERE

                        next();

                    } catch { return; }

            }, function (err) {
                if (err) {

                    console.error(err);

                    rej(err.statusCode);
                    return;

                }

                acpt(ToReturn);

Thank you so much! That did the trick for me.

I am having a similiar issue here. I have my array getting created of the records I want, but when I return the array, the promise that is after the function call returns an empty value. Any tips for me?


async function getRecords() {
      
     data =updateTable.select({
        fields:['building_name']
    }).eachPage(function page(records, fetchNextPage){
        
        records.forEach(function(record){
            num++
            //console.log(num)
            try{
             //console.log(record['fields']['building_name'])
             
             buildings.push(record['fields']['building_name'])
            }
            catch(err){
                console.log('hello1')
                console.log(err)
            }

        }) 
            try{
        fetchNextPage()
            }
            
            catch{
                console.log('hello2')
                return buildings;
            }
    },function (err) {
        console.log(err)
        console.log('hello3')
        if (err) {
            console.log('errror')
            console.log(err);
            return;
        }
        console.log('hello4')
        console.log(buildings)
        console.log('hello5')
        return buildings
        

        
    });   
    }




getRecords().then(function(r){
    console.log('arrayarray')
    console.log(r)
    console.log(array)
 

}

)```

getting the same thing on a new created DB

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'offset')
    at query.js:160:20
    at run_action.js:84:9

curl, and using fetch works without any errors so it must be something about the Airtable library, the DB contains 27 records, I've tried to pull 10, 20, 27, 100 but it always gives the same error.
Using the try ... catch solution above didn't work.

@Airtable, why hasn't it been fixed yet? Have the same issue.

@Airtable, why hasn't it been fixed yet? Have the same issue.

It's been an year over an year since this problem aroused and still no proper solution

Misleading error that happened when I was trying to pull the data that was not existent in the table and read the results. Airtable pls fix this err to make it clear to ppl as to what is happening. Here is my code with the error that I was hitting:

export function getUserDataByUid(userUid) {
  let base = new Airtable({apiKey: process.env.REACT_APP_AIRTABLE_API_KEY}).base('appIdPYOYosoVDlr8');
  return new Promise((res, rej) => {
    try {
      console.log('THIS LINE GETS PRINTED')
      base.table('users').select({
        "filterByFormula": "uid=" + "\"" + userUid + "\""
      }).firstPage((err, results) => {
        if (err) {
          // handle err;
          console.log("REACHED ERR BLOCK")
          console.log(err)
          rej(undefined)
          throw err;
        } else {
          console.log("REACHED RES BLOCK")
          console.log(results[0]) // -> UNDEFINED
          console.log((results[0].fields)) // -> Does not throw 'Cannot find fields of undefined' but 'Cannot read properties of undefined (reading 'offset')'
     //TODO: Add the check below to avoid the error     
if (results.length > 0) {
            res(results[0].fields)
          } else {
            res(undefined)
          }
        }
      })
    } catch (e) {
      console.log('THIS CATCH IS NEVER REACHED')
      console.log(e)
    }
  })
}

this issue still persists, getting the same offset error:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'offset')

Can this be handled within the airtable.js library here

pageCallback(records, next);

?

If the pageCallback call is wrapped in try/catch, catch can then call done(err) and this will be handled more gracefully. What we see currently is some obscure internal error rather than the application-level issue, which slows down debugging the root cause.

try {
    pageCallback(records, next);
} catch (err) {
    done(err, null);
}

Caveat: I'm not really familiar with the internals, just my thoughts from a quick look at the source.

had this issue too (I'm downloading over 100,000 records). I found that adding a a few hundred millisecond sleep/wait after each page solved the issue - so this might be a rate limiting thing as one of the causes