ERROR Cannot read property ‘toLowerCase’ of undefined

Posted by muchag | Nuxt.js |
初回投稿:2021-03-05 (金) 18:30:39 | 最終更新:2021-10-16 (土) 11:39:52

【環境】
create-nuxt-app: 3.5.2
Nuxt.js: 2.15.2
-> 2.15.4
Vue.js: 2.6.12
Node.js: 12.18.2
-> 14.16.1

このエラーは、エラー文は頼りにならないことが多いみたい。

色々なことが原因で、最終的にこういうエラーを吐くことになっているだけなので
毎度、原因を探る作業が必要になりそう。

原因を探るためには、コメントアウトを繰り返し
原因箇所を特定するところから始める。

私の場合は

において、掲題のエラーが出た。

Nginx の設定
気のせい?

以下の記事を書いたのは、Nuxt に触りたての頃。

今振り返ってみると、その後、Nuxt インストール時に
このような現象は起きていないので
気のせいだったかも?

ここまで

Nuxt2.15.2


yarn create nuxt-app hello

と普通にインストールしただけなのに
開発サーバを起動したら

ERROR Cannot read property ‘toLowerCase’ of undefined 11:19:35

at WebSocketServer.handleUpgrade (node_modules/ws/lib/websocket-server.js:193:27)
at WS.handleUpgrade (node_modules/@nuxt/content/lib/ws.js:21:21)
at WS.serve (node_modules/@nuxt/content/lib/ws.js:17:10)
at node_modules/@nuxt/content/lib/middleware.js:12:15
at call (node_modules/connect/index.js:239:7)
at next (node_modules/connect/index.js:183:5)
at next (node_modules/connect/index.js:161:14)
at next (node_modules/connect/index.js:161:14)
at WebpackBundler.middleware (node_modules/@nuxt/webpack/dist/webpack.js:2192:5)

というエラーが出た。

調査

泣きそうになりながら Google 先生へ質問してみた。

nuxt + エラーメッセージ

nuxt Cannot read property ‘toLowerCase’ of undefined

こちらで検索したところ
GitHub:Cannot read property toLowerCase of undefined(2019-07-24)
Qiita:Cannot read property ‘toLowerCase’ of undefinedのとき何を確認すべきか?(2020-12-09)
などが上位にでてきたんだけど
いずれもコーディングミスを原因とするもの。

  • HTML の記述ミス
  • SSR の問題?(よく理解できなかった)
  • javascript による undefine オブジェクトへの参照

どれも新規 Nuxt.js プロジェクトにはありえないので
検索ワードを変更してみることにした。

エラー発生ファイル名 + エラーメッセージ

上記エラーメッセージを引き起こしているファイル名を入れてみた。

WebpackBundler.middleware Cannot read property ‘toLowerCase’ of undefined

で検索すると、WebSocket に関わる記事が最初に出てきた。

中を見ると、エラーメッセージが全く同じ!

@nuxt/content

途中 @nuxt/content が原因っぽいことが書いてあったので
試しに、@nuxt/content を外してインストールしてみると
確かに件のエラーが出ない。

原因その1

更に読み進めると
GitHub:Nginx の WebSocket を有効にすると問題が解消される(2020-10-16)
との返信を見つけた。

解決その1

そこで
Qiita:NginxのリバースプロキシでWebソケットを通す際の設定(2019-12-28)
こちらを参考に、Nginx において WebSocket を有効に設定してみた。


server {
    listen       80;
    server_name  192.168.56.xxx;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

これで確かに
@nuxt/content を同梱してインストールしても
件のエラーは出なくなった。

公式

と、ここまで試行錯誤を繰り返した後で
公式に Nginx のリバースプロキシを利用する設定が載っているのを見つけた。
公式:NGINX Using NGINX as a reverse proxy


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

    location / {
        expires $expires;

        proxy_redirect                      off;
        proxy_set_header Host               $host;
        proxy_set_header X-Real-IP          $remote_addr;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto  $scheme;
        proxy_read_timeout          1m;
        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

こちらで試したところ、件のエラーが出た。

WebSocket 有効化

そこで、前述の WebSocket を有効にする設定を加えた。


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

    location / {
        expires $expires;

        proxy_redirect                      off;
        proxy_set_header Host               $host;
        proxy_set_header X-Real-IP          $remote_addr;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto  $scheme;
        proxy_read_timeout          1m;
        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

エラーが出る。。。

直アクセス

curl http://localhost:3000/

と、直接アクセスしたときはエラーが出ないので
やっぱり Nginx の問題だと思われる。

リバースプロキシ排除

location ディレクティブ内のリバースプロキシの設定をコメントアウトしてみた。


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

    location / {
        expires $expires;

#        proxy_redirect                      off;
#        proxy_set_header Host               $host;
#        proxy_set_header X-Real-IP          $remote_addr;
#        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
#        proxy_set_header X-Forwarded-Proto  $scheme;
#        proxy_read_timeout          1m;
#        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

エラーが出ない!

proxy_set_header

いっぱいコメントアウトしたので、選別をしたところ


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

    location / {
        expires $expires;

        proxy_redirect                      off;
#        proxy_set_header Host               $host;
#        proxy_set_header X-Real-IP          $remote_addr;
#        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
#        proxy_set_header X-Forwarded-Proto  $scheme;
        proxy_read_timeout          1m;
        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

これならエラーが出ない。
proxy_set_header があるとエラーが出ることが判明。

リバースプロキシを location の外へ

途方に暮れていたところ
なんとなく、proxy_set_header を location ディレクティブの外へ配置してみた。


map $sent_http_content_type $expires {
    "text/html"                 epoch;
    "text/html; charset=utf-8"  epoch;
    default                     off;
}

server {
    listen          80;             # the port nginx is listening on
    server_name     your-domain;    # setup your domain here

    gzip            on;
    gzip_types      text/plain application/xml text/css application/javascript;
    gzip_min_length 1000;

+   proxy_http_version 1.1;
+   proxy_set_header Upgrade $http_upgrade;
+   proxy_set_header Connection "upgrade";

+   proxy_set_header Host               $host;
+   proxy_set_header X-Real-IP          $remote_addr;
+   proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
+   proxy_set_header X-Forwarded-Proto  $scheme;

    location / {
        expires $expires;

        proxy_redirect                      off;
        proxy_read_timeout          1m;
        proxy_connect_timeout       1m;
        proxy_pass                          http://127.0.0.1:3000; # set the address of the Node.js instance here
    }
}

エラーが出ない!

解決その2???

解決したとは思えないけど
疲れたので、アプリ側を実装するまで、一旦これでよしとする。。。

参考サイト

GitHub:Websocket error using alternative server framework(2020-06-14)

PLEASE SLEEP:nginx の proxy_set_header の継承ではまった(2013-05-18)
-> 調査の過程でこんな記事も見つけたので、一応メモ。古い記事なので、今は仕様が変わっているかも

v-if の使い方(位置)

久しぶりにこのエラーに遭遇した。

エラー
TypeError: Cannot read properties of undefined (reading ‘toLowerCase’)

前回と文言が異なるのは、Nuxt の仕様変更かしらね?

原因

コメントアウトを繰り返し、箇所を特定したところ

~/components/Loader.vue

ここだった。

解決

とりあえず一個上のDOMにv-ifを移動して解決。

ハッカーになりたい!:Nuxt.jsの$route.pathは$nuxt.$route.pathを使え!(2018-09-04)

という記事を見かけたので


こうしたら、エラーが出なくなった。

言われてみれば、元のコードだと
template 直下に v-if が仕込まれているので
状況によっては、template 内が空になるコードとなっている。

これは Nuxt の仕様的に、確かアウトだったような。。。
そのせいか~ 🙄

Posted by muchag | Nuxt.js |
初回投稿:2021-03-05 (金) 18:30:39 | 最終更新:2021-10-16 (土) 11:39:52