Меню

Cannot read properties of undefined reading length ошибка

One of the most common errors we record, “Cannot read properties of undefined (reading ‘length’)”, turned up in our own logs recently while looking into an issue with Microsoft Edge and the Facebook sdk. Let’s dive into this error, what it means, and how to fix it.

Breaking down the Message

TypeError: Cannot read properties of undefined (reading 'length')

In older browsers, this might also be shown as:

Cannot read property 'length' of undefined

TypeError is a subset of JavaScript Error that is thrown when code attempts to do something that does not exist on the target object.

This message indicates that our code expects to have an object with a length property, but that object was not present. length is commonly used on string and array, but a custom object could also have this property.

This is a blocking error, and script execution will stop when this error occurs.

Understanding the Root Cause

This error can be thrown for a lot of reasons, as it is incredibly common to reference the length property of string or array during everyday development. For example, if we had a function that acts on a string argument, but is called without a string, we would see this error.

function foo(myString) {
  if (myString.length >= 10) {
    // do something
  }
}

foo(); // Whoops! TypeError
undefined passed to string function

In our case, we were intercepting a call to fetch, and we had assumed the url property would be a string.

But, dear developer, it was not always a string. 🤦‍♂️.

We had some code like this that intercepted fetch requests and recorded some metadata if the request was correct. It looked something like this:

ourInterceptedFetch(options) {
  if (options.url.length <= 0) {
    // fail out
  }
}
Defensive checking a string

We were doing appropriate defensive type checking to make sure that the options argument had a valid url property. Unfortunately, fetch also accepts options to be any object with a stringifier: an object with a toString method. Like this:

fetch({
  toString: function() {
    return `https://whatever.com/`;
  }
});
Serializable object passed to fetch

In this case, options.url is undefined, so when we try to check options.url.length, it blows up with our error, “Cannot read property ‘length’ of undefined”. Ugh.

While this may be valid, it is a bit weird, right? We thought so too.

How to Fix It

So how do we fix this and prevent it from happening again?

1. Understand why your object is undefined

Understand why your object is undefined

First and foremost, you need to understand why this happened before you can fix it. You are probably not doing exactly the same thing we are, so the reason your object is undefined may be somewhat different. Consider:

  • Are you relying on a network response to be a certain shape?
  • Are you processing user-input?
  • Is an external function or library calling into your code?

Or maybe its just a logical bug somewhere in your code.

2. Add Defensive Checking

Add Defensive Checking

Anytime you don’t completely control the input into your code, you need to be defensively checking that arguments have the correct shape. API response change, functions get updated, and users do terrible, terrible things.

For instance, if you have a fetch request that receives a JSON response with a foo string property, you might have a defensive check that looks like this:

fetch("https://example.com/api")
  .then(resp => {
    return resp.json();
  })
  .then(json => {
    if (!json || typeof json.foo != 'string') {
      // Record an error, the payload is not the expected shape.
    }
  });
Defensive checking a fetch response

3. Monitor Your Environment

 Monitor Your Environment

You’ll need to make sure that the issue is really fixed and that the problem stops happening. Mistakes happen, APIs change, and users are unpredictable. Just because your application works today, doesn’t mean an error won’t be discovered tomorrow. Tracking when exceptional events happen to your users gives you the context to understand and fix bugs faster. Check out TrackJS Error Monitoring for the fastest and easiest way to get started.

Are you experiencing the “cannot read property ‘length’ of undefined” error in JavaScript? This error occurs when you attempt to access the length property from a variable that has a value of undefined.

const arr = undefined;

// TypeError: Cannot read properties of undefined (reading 'length')
const length = arr.length;

console.log(length);

To fix the “cannot read property ‘length’ of undefined” error, perform an undefined check on the variable before accessing the length property from it. There are various ways to do this.

1. Use an if Statement

We can use an if statement to check if the variable is truthy before accessing the length property:

const arr = undefined;

let arrLength = undefined;

// Check if "arr" is truthy
if (arr) {
  arrLength = arr.length;
}

console.log(arrLength); // undefined


const str = undefined;

let strLength = undefined;

// Check if "str" is truthy
if (str) {
  strLength = str.length;
}

console.log(strLength); // undefined

2. Use Optional Chaining

We can use the optional chaining operator (?.) to return undefined and prevent the method call if the variable is nullish (null or undefined):

const arr = undefined;

// Use optional chaining on "arr" variable
const arrLength = arr?.length;

console.log(arrLength); // undefined


const str = undefined;

// Use optional chaining on "str" variable
const strLength = str?.length;

console.log(strLength); // undefined

3. Access the length Property of a Fallback Value

We can use the nullish coalescing operator (??) to provide a fallback value to access the length property from.

const arr = undefined;

// Providing an empty array fallback
const arrLength = (arr ?? []).length;

console.log(arrLength); // 0


const str = undefined;

// Providing an empty string fallback
const strLength = (str ?? '').length;

console.log(strLength); // 0

The nullish coalescing operator (??) returns the value to its left if it is not null or undefined. If it is, then ?? returns the value to its right.

console.log(2 ?? 5); // 2
console.log(undefined ?? 5); // 5

We can also use the logical OR (||) operator to provide a fallback value from which to access the length property.

const arr = undefined;

// Providing an empty array fallback
const arrLength = (arr || []).length;

console.log(arrLength); // 0

const str = undefined;

// Providing an empty string fallback
const strLength = (str || '').length;

console.log(strLength); // 0

Like the ?? operator, || returns the value to its left if it is not null or undefined. If it is, then || returns the value to its right.

4. Use a Fallback Value Instead of Accessing the length Property

We can also combine the optional chaining operator (?.) and the nullish coalescing operator (??) to provide a fallback value to use as the result, instead of accessing the length property from the undefined value.

const arr = undefined;

// Using "0" as a fallback value
const arrLength = arr?.length ?? 0;

console.log(arrLength); // 0


const str = undefined;

// Using "0" as a fallback value
const strLength = str?.length ?? 0;

console.log(strLength); // 0

As we saw earlier, the logical OR operator (||) can replace the ?? operator in cases like this:

const arr = undefined;

// Using "0" as a fallback value
const arrLength = arr?.length || 0;

console.log(arrLength); // 0

const str = undefined;

// Using "0" as a fallback value
const strLength = str?.length || 0;

console.log(strLength); // 0

11 Amazing New JavaScript Features in ES13

This guide will bring you up to speed with all the latest features added in ECMAScript 13. These powerful new features will modernize your JavaScript with shorter and more expressive code.

11 Amazing New JavaScript Features in ES13

Sign up and receive a free copy immediately.

Ayibatari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

The issue happen with v4 version (tested on v4.0.3, v4.0.5 and the latest v4.1.2)

With the same config and code base it compile with no problem in v3.9

Expected behavior:

No such error! No failing at internal level! (Plus it works in v3.9 and not v4)

text should not come as undefined! Or should be handled without problem!

Actual behavior:
In v3.9 the code compile with the same config with no problem! In v4 i get Cannot read property ‘length’ of undefined error! And internal failing!

Through the error stack! i get where the error happened and it was at the function computeLineStarts!
text is coming undefined! i did some console logging! And i got what file was been treated! And what text node were printing! The file is all normal and correct! A comment at the end was the last thing which after it the code fail!

Then i added another instruction after it! (A variable assignment const someVar = '';) and the error went up! The last treated nodes before failing came more up! Here bellow the file at which my console.logging stopped at!

File on which the resolution failed at:

https://gist.github.com/MohamedLamineAllal/472cf2043a100cb03244de5fb1138034

When i added const someVar = ""; at the end! the last treated node was } from

export interface IWebSocketDriver {
  readonly protocol: string;
  readonly readyState: number;
  readonly url: string;
  binaryType: BinaryType;
  readonly CONNECTING: number;
  readonly OPEN: number;
  readonly CLOSING: number;
  readonly CLOSED: number;
  setGetStreamObj: (getStreamObj: () => WebSocket | IWebSocketDriver) => IWebSocketDriver;
  onInit: () => IWebSocketDriver;
  onopen: ((this: IWebSocketDriver, ev: Event) => any) | null;
  onmessage: ((this: IWebSocketDriver, ev: MessageEvent) => any) | null;
  onclose: ((this: IWebSocketDriver, ev: CloseEvent) => any) | null;
  onerror: ((this: IWebSocketDriver, ev: Event) => any) | null;
  close(code?: number, reason?: string): void;
  send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;
} // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<!!!!!!!!!!!!!!! here the last treated element

/**
 * THINGS TO DO:
 * =============
 *
 *  decide and define the response output of all the functions
 *
 *  consider a design that add useful information that are exchange platform dependent
 *
 *
 *
 * STREAMS :
 * Need to precise what form the returned object should have
 *
 * ok dodo
 */
const someVar = ''; // <=== added this

How i debugged!?

in tsc.js

ts.stringToToken = stringToToken;
    function computeLineStarts(text) {
        console.log('text: ') // <<<==== here
        console.log(text)
        var result = new Array();
        var pos = 0;

And at

ts.getNonDecoratorTokenPosOfNode = getNonDecoratorTokenPosOfNode;
    function getSourceTextOfNodeFromSourceFile(sourceFile, node, includeTrivia) {
        console.log('Source file: ') // <<<<<<<<<<<<<<<<<<<<<<<<= here
        console.log(sourceFile.path)
        console.log('================+++>')
        if (includeTrivia === void 0) { includeTrivia = false; }
        return getTextOfNodeFromSourceText(sourceFile.text, node, includeTrivia);
    }

First Compilation execution (original file)

Without adding the last const someVar = '';

https://gist.github.com/MohamedLamineAllal/653fd4f597aa821f416a33e86d4514eb

Second compilation (after adding the last line)

https://gist.github.com/MohamedLamineAllal/022f6f285313aec30b82bb72238bcaeb

Always it fails at computeLineStarts() method! And because text is undefined.

Error stack

TypeError: Cannot read property 'length' of undefined
    at computeLineStarts (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:6528:27)
    at Object.getLineStarts (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:6581:60)
    at getCurrentLineMap (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:81810:59)
    at emitDetachedCommentsAndUpdateCommentsInfo (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:85144:94)
    at emitBodyWithDetachedComments (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:85007:17)
    at emitSourceFile (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:83873:21)
    at pipelineEmitWithHint (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:81887:24)
    at noEmitNotification (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:80586:9)
    at onEmitNode (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:70565:13)
    at onEmitNode (/home/coderhero/.nvm/versions/node/v15.0.1/lib/node_modules/typescript/lib/tsc.js:72333:13)

For the shared links i used typescript Version 4.1.2! Otherwise i tested with v4.0.3 and v4.0.5

tsconfig.json

{
  "compilerOptions": {
    "declaration": true,
    "declarationDir": "./dist",
    "module": "commonjs",
    "noImplicitAny": true,
    "lib": ["ESNext", "DOM"],
    "outDir": "./dist",
    "target": "es6",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "esModuleInterop": true
  },
  "typedocOptions": {
    "mode": "modules",
    "out": "docs"
  },
  "include": ["src/**/*.ts", "src/**/*.json", "test"],
  "exclude": ["node_modules", "dist", "src/**/*.spec.ts", "src/**/*.test.ts"]
}

Related Issues:

  • TypeError: Cannot read property ‘length’ of undefined in computeLineStarts #40747
  • TypeError: Cannot read property ‘length’ of undefined in watch mode and {allowJS: true} #35074

I am trying to read the json document from php and convert it needed in js, but an error occurs. :
cannot read properties of undefined (reading ‘length’)
What went wrong? How can I loop the result below without using length ?

Here’s the code:

What I have tried:

/*php */

$conn = db_connect();
$id = mysqli_fix_string( $conn, $id );

$Json_file = file_get_contents("files/sub/".$id."/".sub.json);
print( $json_file );

/*.js */
$.ajax({ url: "./sub/view_sub.php",
         type:"GET",
         data: { id: id },
         success: function( json ) {
            const result = JSON.parse( json );
            console.log(result.sub)
            console.log(result.sub[1]); // OK result is 'serg' 
            console.log(result.sub[2]); // OK result is 'dgf
            if( result.sub.length > 0 ){   <<== error
                 let i = 0;
                 for( const item of result.sub ){
                     foo_arr[id].input_text(i++, item );
                  }
               }
           }
});
              
// console result
>{1: 'serg', 2: 'dgf', 4: 'dfg ', 6: 'dfge ergre'}  <== console.log(result.sub)
uncaught typeError: Cannot read properties of undefined (reading 'length')


Solution 2

Quote:

This is my result /

console.log(result.sub)
{1: 'serg', 2: 'dgf', 4: 'dfg ', 6: 'dfge ergre'} 

Your result is not an array; it’s an object which happens to have numeric property names.

If you want to iterate over the properties of the object, you can use the Object.keys method[^]:

const subKeys = Object.keys(result.sub);
for (let i = 0; i < subKeys.length; i++) {
    foo_arr[id].input_text(i, result.sub[subKeys[i]]);
}

Comments

Solution 1

Try using:

if( result.length > 0 )

Example:

const fruits = ["Banana", "Orange", "Apple", "Mango"];
let length = fruits.length;

result returns:

4

Comments

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

 

Print

Answers RSS

Top Experts
Last 24hrs This month

CodeProject,
20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8
+1 (416) 849-8900

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Cannot place this file no filter found for requested operation ошибка indesign
  • Cannot perform a dml operation inside a query ошибка