Salesforce DXのforce:source:pushで「The "path" argument must be of type string.」エラーが出る時 #salesforce

ある時Salesforce DX (SFDX)の force:source:push で次のエラーが出ました。

$ sfdx force:source:push
ERROR:  The "path" argument must be of type string.

その時の対処法についてのメモです。

いきなり結論

*-meta.xml に対応するファイル(もしくはフォルダ)が正しく存在するか確認しましょう。

今回のケースでは、静的リソースフォルダ ( force-app/main/default/staticresources )に hoge.resource-meta.xml というファイルがあるのに、実際のリソースファイル(もしくはフォルダ)がないことが原因でした。

調査記録

原因を特定するために行ったことなどの記録です。

詳しいエラーメッセージを出してみる

一行だけのエラーメッセージでは原因に皆目検討がつかないので、 --json オプションをつけてもう少し詳細なエラーメッセージが表示されるようにします。 (出力形式をJSONにすることでなぜエラー出力が詳細になるのか?という疑問はさておき…)

するとこんな感じでした。

$ sfdx force:source:push --json
{"message":"The \"path\" argument must be of type string","status":1,"stack":"TypeError [ERR_INVALID_ARG_TYPE]: The \"path\" argument must be of type string\n    at assertPath (path.js:28:11)\n    at Object.resolve (path.js:1184:7)\n    at Object.copy (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/salesforce-alm/node_modules/fs-extra/lib/copy/copy.js:27:28)\n    at Object.copy (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/universalify/index.js:5:67)\n    at Object.tryCatcher (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/bluebird/js/release/util.js:16:23)\n    at Object.ret [as copyAsync] (eval at makeNodePromisifiedEval (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/bluebird/js/release/promisify.js:184:12), <anonymous>:15:23)\n    at Promise.resolve.then (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/salesforce-alm/dist/lib/sourceConvertApi.js:143:46)\n    at tryCatcher (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/bluebird/js/release/util.js:16:23)\n    at Promise._settlePromiseFromHandler (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/bluebird/js/release/promise.js:510:31)\n    at Promise._settlePromise (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/bluebird/js/release/promise.js:567:18)\n    at Promise._settlePromiseCtx (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/bluebird/js/release/promise.js:604:10)\n    at Async._drainQueue (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/bluebird/js/release/async.js:143:12)\n    at Async._drainQueues (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/bluebird/js/release/async.js:148:10)\n    at Immediate.Async.drainQueues [as _onImmediate] (/Users/xxx/.nodebrew/node/v9.2.0/lib/node_modules/sfdx-cli/node_modules/bluebird/js/release/async.js:17:14)\n    at runCallback (timers.js:800:20)\n    at tryOnImmediate (timers.js:762:5)","name":"TypeError [ERR_INVALID_ARG_TYPE]","warnings":[]}

うーん、イマイチよくわかりませんね…。慣れている人ならピンとくるのかもしれませんが…。

sfdx-cliを最新にしてみる

最新バージョンにアップデートしました。

$ npm install --global sfdx-cli

(結果)状況変わらず…。

地道に原因を潰していく

どこのリビジョンからpushできなくなったのかを切り分けていき、原因を見極めていきます。
こういう時のためにも、意味のある最小単位で小さくコミットしていくことは重要ですね(自戒)

で、原因は、静的リソースのファイル不足であることがわかりました。

sfdxプロジェクトで開発をしている場合でも、webpackなどのNode.jsのエコシステムを使って静的リソースをビルドしてたので、ビルドの成果物をバージョン管理に含まれないようにするため、 .gitignore でこんなことを書いていたんですね…。

force-app/main/default/staticresources/**
!force-app/main/default/staticresources/*-meta.xml

そのため、ある人の環境できちんと動作でき、リポジトリに忘れずにpushされたはずの状態でも、別の人の環境で静的リソースファイルが存在せず、pushできなかった、という状況が起きていたようです。