PHPUnitのバージョン上げようとして嵌った
環境
- Laravel 5.3.x / Laravel 5.5.x の2つのアプリケーションが存在
- PHP 7.2.x
やりたいこと
どちらも最新バージョンのPHPUnit(8.x)が使いたい
事象と原因
Laravel 5.3.xのアプリケーション
PHP Fatal error: Class 'PHPUnit_Framework_TestCase' not found in application/path/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php on line 11
このエラーが発生
Laravel5.4からPHPUnitのクラス名の名前空間化?に対応したらしく、 以下の記述をするLaravel5.3でエラーが発生
use PHPUnit_Framework_TestCase; abstract class TestCase extends PHPUnit_Framework_TestCase
Laravel5.4以降
use PHPUnit\Framework\TestCase as BaseTestCase; abstract class TestCase extends BaseTestCase
対応策
PHPUnitのバージョンを上げない
細かく言うと
- vendor配下のモジュールのためオーバーライドする必要がある(と思う)
- バージョンを上げることはwantであり、mustではない
Laravel 5.5.xのアプリケーション
PHP Fatal error: Declaration of Illuminate\Foundation\Testing\TestCase::setUp() must be compatible with PHPUnit\Framework\TestCase::setUp(): void in application/path/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php on line 12
ググってもよく分からなくて、後輩に聞いたら教えてくれた。
Return Type of Template Methods The methods listed below now have a void return type declaration:
PHPUnit\Framework\TestCase::setUpBeforeClass() PHPUnit\Framework\TestCase::setUp() PHPUnit\Framework\TestCase::assertPreConditions() PHPUnit\Framework\TestCase::assertPostConditions() PHPUnit\Framework\TestCase::tearDown() PHPUnit\Framework\TestCase::tearDownAfterClass() PHPUnit\Framework\TestCase::onNotSuccessfulTest() Your implementations of the methods listed above now must be declared void, too, otherwise you will get a compiler error.
この一文にびっくり「otherwise you will get a compiler error.」
ということで、上記に当てはまるメソッドに対して、
: void
を記述したらエラーが解消された。
/** * Setup the test environment. * * @return void */ protected function setUp(): void {
対応策
PHPUnitのバージョンを上げない
細かく言うと
- Laravel5.3のときと同様に、vendor配下のモジュールのためオーバーライドする必要がある(と思う)
- 既存のテストコードに対しても修正が必要で、意外と工数が掛かることが判明
既存のテストコードでのエラー
/** * XXXXXTest constructor. * * @param string|null $name * @param array $data * @param string $dataName */ public function __construct(string $name = null, array $data = [], string $dataName = '') {
__constructをこう実装していたのだが、
PHP Fatal error: Uncaught TypeError: Argument 3 passed to Tests\Feature\XXXXXTest::__construct() must be of the type string, integer given
エラーが発生してしまった。
/** * GetUserTest constructor. * * @param string|null $name * @param array $data * @param $dataName */ public function __construct(string $name = null, array $data = [], $dataName = '') {
こう直したら動いたのだが、Warningが発生しててあまり綺麗とは言えなかった。
PHPUnit 8.0.4 by Sebastian Bergmann and contributors. Warning - The configuration file did not pass validation! The following problems have been detected: Line 26: - Element 'log', attribute 'logIncompleteSkipped': The attribute 'logIncompleteSkipped' is not allowed. Test results may not be as expected. ......... 9 / 9 (100%) Time: 3.07 seconds, Memory: 24.00 MB
補足
戻り値の型問題は、Laravel5.8で修正されているので、
Laravel5.7 以下ではPHPUnit8.xは使わない方がよさそう。という見解を得られた。
Laravelのセッションが消えて困った
概要
画面間で遷移させているときに、一部のセッションキーが消えてしまったときの話 (Laravelのバージョンは5.3)
ざっくりと
(先に断っておくが、変数やメソッド名は仮)
少し雑だが、こんなformからPOSTで画面Aに遷移しようとする際に
<form action="https://abc.com/" method="post" name=""> <input type="input" name="client_id" value="hoge"><br> <input type="input" name="redirect_uri" value="https://yyy.com"><br> <input type="submit" value='BUTTON'> </form>
こんな形でセッションに突っ込んでたら、
/** * /に対応するControllerのAction */ public function index(Request $request) { session()->put('client_id', $request->input('client_id')); session()->put('redirect_uri', $request->input('redirect_uri')); return view('index'); }
以下のようにsessionからgetができなくて困った
/** * indexのviewからPOST送信先のControllerのAction */ public function add(Request $request) { session()->get('client_id'); // ←取得できずnullになる session()->get('redirect_uri'); // ←取得できずnullになる
調査内容
このように、view遷移前、POST送信直後のそれぞれに dd(session()->all());
を入れてみて、
セッションの構造がどうなっているかを調べた
dd(session()->all()); // 追加 return view('index'); } public function add(Request $request) { dd(session()->all()); // 追加
結果
return view直前での詳細
array:11 [▼ "_previous" => array:1 [▼ "url" => "http://******" ] "_flash" => array:2 [▼ "old" => [ "client_id" => "hoge", "redirect_uri" => "https://yyy.com", ] "new" => [] ] "_token" => "**************************" "client_id" => "hoge", "redirect_uri" => "https://yyy.com", "hoge" => "hoge", "fuga" => "fuga", "id" => 111111111, ]
function addでの詳細
array:11 [▼ "_previous" => array:1 [▼ "url" => "http://******" ] "_flash" => array:2 [▼ "old" => [] "new" => [] ] "_token" => "**************************" "hoge" => 'hoge' "fuga" => "fuga" "id" => 111111111 ]
という感じだった
考察
現在のところは原因が分かってないが、
_flash
の old
に入ってると、処理終了時(response返却後?)にセッションからそのキーを抹消するのでは?と思っている
(Illuminate\Session\Store.php
を読んだら、結果が分かりそう)
補足
たしかに以下のように reflash()
を追加したらセッションは維持された
/** * /に対応するControllerのAction */ public function index(Request $request) { session()->put('client_id', $request->input('client_id')); session()->put('redirect_uri', $request->input('redirect_uri')); $request->session()->reflash(); return view('index'); }
追記
LaravelのSessionはここ
この terminate
つまり、処理終了後にSessionが削除されていた。
/** * Perform any final actions for the request lifecycle. * * @param \Illuminate\Http\Request $request * @param \Symfony\Component\HttpFoundation\Response $response * @return void */ public function terminate($request, $response) { if ($this->sessionHandled && $this->sessionConfigured() && ! $this->usingCookieSessions()) { $this->manager->driver()->save(); } }
で、実処理はこれ
考察は間違っていなかったようだった。
Laravelの「integer」ルールのバリデーション
概要
LaravelのValidationルールで「integer」があるが、これは型までチェックしているのか?と思ったのが調べるきっかけ。
どういうことかというと、
'id' => 'required|integer',
と書いていたバリデーションルールに対して、string型での数値が通っていた。
LaravelにおけるValidationの流れ
そもそもの話
ざっくり書くとControllerでこのようにValidationを実行しているが、
use ValidatesRequests; $this->validate($request, $this->validator->getRules(), $this->validator->getMessage(), $this->validator->getAttribute());
このときの処理の流れは、
①
vendor\laravel\framework\src\Illuminate\Foundation\Validation\ValidatesRequests.php: validate()
②
vendor\laravel\framework\src\Illuminate\Validation\Validator.php: validate()
③
vendor\laravel\framework\src\Illuminate\Validation\Validator.php: fails()
④
vendor\laravel\framework\src\Illuminate\Validation\Validator.php: passes()
⑤
vendor\laravel\framework\src\Illuminate\Validation\Validator.php: validateAttribute()
Validationの実体
validateAttributeの中身がこんな感じ
/** * Validate a given attribute against a rule. * * @param string $attribute * @param string $rule * @return void */ protected function validateAttribute($attribute, $rule) { $this->currentRule = $rule; list($rule, $parameters) = ValidationRuleParser::parse($rule); if ($rule == '') { return; } // First we will get the correct keys for the given attribute in case the field is nested in // an array. Then we determine if the given rule accepts other field names as parameters. // If so, we will replace any asterisks found in the parameters with the correct keys. if (($keys = $this->getExplicitKeys($attribute)) && $this->dependsOnOtherFields($rule)) { $parameters = $this->replaceAsterisksInParameters($parameters, $keys); } $value = $this->getValue($attribute); // If the attribute is a file, we will verify that the file upload was actually successful // and if it wasn't we will add a failure for the attribute. Files may not successfully // upload if they are too large based on PHP's settings so we will bail in this case. if ($value instanceof UploadedFile && ! $value->isValid() && $this->hasRule($attribute, array_merge($this->fileRules, $this->implicitRules)) ) { return $this->addFailure($attribute, 'uploaded', []); } // If we have made it this far we will make sure the attribute is validatable and if it is // we will call the validation method with the attribute. If a method returns false the // attribute is invalid and we will add a failure message for this failing attribute. $validatable = $this->isValidatable($rule, $attribute, $value); if ($rule instanceof RuleContract) { return $validatable ? $this->validateUsingCustomRule($attribute, $value, $rule) : null; } $method = "validate{$rule}"; if ($validatable && ! $this->$method($attribute, $value, $parameters, $this)) { $this->addFailure($attribute, $rule, $parameters); } }
これを見ると、integer
の場合、validateInteger
でvalidationが実行されそう。
なので追ってみた。
$method = "validate{$rule}"; if ($validatable && ! $this->$method($attribute, $value, $parameters, $this)) { $this->addFailure($attribute, $rule, $parameters); }
/** * Validate that an attribute is an integer. * * @param string $attribute * @param mixed $value * @return bool */ public function validateInteger($attribute, $value) { return filter_var($value, FILTER_VALIDATE_INT) !== false; }
ということで、結局は filter_var($value, FILTER_VALIDATE_INT)
FILTER_VALIDATE_INTを調べた
とりあえず読んでみた
It's good to remember that using filter_var is primarily for filtering input values when doing boolean logic comparisons. Take the following: $value = "12"; if(filter_var($value, FILTER_VALIDATE_INT)) { // validated as an int }
これを読むと Stringっぽくクォートで囲った値を送っても、intとして処理が通りそう。
結論
型というより、整数形式の表現だったら、何でも通るのではないかと思った。
補足
1ヶ月くらい前に下書きで書いてて、公開するの忘れてたやつ。
LaravelのPHPUnitで「PDOException: SQLSTATE[HY000] [1040] Too many connections」が起きた
概要
Laravelでテスト実行中に以下のエラーが出るようになり、少し悩んだ
※バージョンは「Laravel 5.5.44」
PDOException: SQLSTATE[HY000] [1040] Too many connections
- エラーの発生箇所はPHPUnitで流しているケースの後半
- エラーが起きたテストクラスを単独で実行するとエラーは発生しない
という状況のため、単純にテストケースごとにConnectionを切る方向で考えた。
参考
とりあえず他に悩んでる人がいないかググった。
対応
上記のQiitaの方は PDO::ATTR_PERSISTENT
で対応したみたいだったが、
本番稼働中のサービスもあり、迂闊にConfigを変えるのは良くない気もしたので、
当初の想定通りに、テストケースごとにConnectionを切ることにした。
/* * @return void */ public function tearDown() { \DB::connection()->disconnect(); // 追加 parent::tearDown(); }
終わりに
RefreshDatabaseTrait
をいろいろカスタマイズしており、$this->beginDatabaseTransaction();
が実行されていないことが原因だと思う
PHP7.2からのcount()の挙動に悩んだ
概要
PHPのバージョンを7.0(7.0.15)から7.2(latest)に上げたときに起きた問題
エラーの内容
php7.2 count
でググればたくさん出てくるので、細かいことは省略するが、
count()
の仕様変更により、配列などCountable
なものではないとエラーを返すようになった。
PHP Warning: count(): Parameter must be an array or an object that implements Countable
PHP7.0での挙動
いくつか試してみた。思いつく限り。
var_dump(count('')); // →int(1) var_dump(count('hoge')); // →int(1) var_dump(count('0')); // →int(1) var_dump(count('1')); // →int(1) var_dump(count('2')); // →int(1) var_dump(count(0)); // →int(1) var_dump(count(1)); // →int(1) var_dump(count(2)); // →int(1) var_dump(count([])); // →int(0) var_dump(count([''])); // →int(1) var_dump(count(['',''])); // →int(2) var_dump(count(['1',''])); // →int(2) var_dump(count(null)); // →int(0) var_dump(count(true)); // →int(1) var_dump(count(false)); // →int(1)
やりたかったこと
誰かが作った既存のメソッドがあって、
public function getHoge($fuga) { return count($fuga->getPiyo()); }
これのI/Fを担保したかった。影響範囲がよくわからないから。
どうしたのか
上記の挙動を見る限り、
- 配列かどうか
- NULLかどうか
の判定で済みそうだと思ったので、いったんは以下にしてみる。 本当はもっと厳密にあらゆることを想定する必要があるはず。
public function getHoge($fuga) { if (is_array($fuga->getPiyo())) { return count($fuga->getPiyo()); } return is_null($fuga->getPiyo()) ? 0 : 1; }
まとめ
そもそもなぜこのエラーに出くわしたかというと、新規で開発をしてたときに、過去のテストコードが通らなくなったから。
要はテストコードって大事だよね、という話なのかもしれない。
リトライ処理のTraitを作ってみた
ずいぶん前に個人的に作ってたものを備忘録で記載。
Exponential Backoff and Jitterで。 TODOで残してるとこがダサいけど、ベスプラがよくわからず。
こういうところを極めるなら、まずは数学をおさらいしなければかなと思う。
trait RetryTrait { /** * リトライ処理回数内部カウント用 * @var int */ private $retryCount = 0; /** * @var bool */ private $jitterEnabled = true; /** * @param string $function * @param array $options * @param int $maxAttempts * @param int $interval micro_sec * @return mixed * @throws \Exception */ public function retry(string $function, array $options = [], int $maxAttempts = 5, int $interval = 1000000) { $result = false; for ($i = 0; $i < $maxAttempts + 1; $i++) { try { // 成功時にはそのまま処理終了 $result = $this->$function($options); break; } catch (\Exception $e) { // 失敗時にはExceptionを返却 $result = $e; } // リクエスト上限到達でリトライ中止 if ($this->retryCount == $maxAttempts) { throw $result; } $this->retryCount++; // インターバルをおいて、次回処理へ $this->interval($interval); } return $result; } /** * リトライ回数から遅延秒数を決定し、処理を止める(sleep) * * @param int $maxAttempts * @param int $interval */ public function interval(int $interval) { /** * TODO 根拠のない数式のため、ベスプラがあればそちらに差し替える */ $waitTime = pow(2, $this->retryCount) / ($this->retryCount + 1) * $interval; usleep($this->jitter($waitTime)); } /** * ±10%のばらつきを与える * Jitterが不要な場合はそのまま返却 * * @param int $waitTime * @return int */ public function jitter(int $waitTime): int { return $this->jitterEnabled ? mt_rand($waitTime * 0.9, $waitTime * 1.1) : $waitTime; } }
実際に使うときはこんな感じ
use RetryTrait; const MAX_ATTEMPTS = 5; /** * リトライ時のインターバル(初期秒数:micro_sec) */ const RETRY_INTERVAL = 1000000; $this->retry('callback', [$param1, $param2], self::MAX_ATTEMPTS, self::RETRY_INTERVAL); /** * @param array $options * @return mixed * @throws \Exception */ public function callback(array $options) { // 何かしらの処理 }
※動作保証はしてない
ServerlessFrameworkでのdeploy時にエラーが出る
概要
serverless deploy
でデプロイした際に、エラーメッセージが出るのだが、
-v
と -verbose
で違いがあった(調べた感じではどっちも同じだと思ってた)
StackTraceを見る感じ、Serverless内でエラーになってるっぽいからバグなのかなぁ。。
環境
Your Environment Information ----------------------------- OS: linux Node Version: 8.12.0 Serverless Version: 1.32.0
Cannot read property 'replace' of undefined
$ serverless deploy -v Serverless: Packaging service... Serverless: Excluding development dependencies... Type Error --------------------------------------------- Cannot read property 'replace' of undefined For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable. Get Support -------------------------------------------- Docs: docs.serverless.com Bugs: github.com/serverless/serverless/issues Issues: forum.serverless.com Your Environment Information ----------------------------- OS: linux Node Version: 8.12.0 Serverless Version: 1.32.0
デバッグをしてみる
$ SLS_DEBUG=* serverless deploy -v Serverless: Load command config Serverless: Load command config:credentials Serverless: Load command create Serverless: Load command install Serverless: Load command package Serverless: Load command deploy Serverless: Load command deploy:function Serverless: Load command deploy:list Serverless: Load command deploy:list:functions Serverless: Load command invoke Serverless: Load command invoke:local Serverless: Load command info Serverless: Load command logs Serverless: Load command login Serverless: Load command logout Serverless: Load command metrics Serverless: Load command print Serverless: Load command remove Serverless: Load command rollback Serverless: Load command rollback:function Serverless: Load command slstats Serverless: Load command plugin Serverless: Load command plugin Serverless: Load command plugin:install Serverless: Load command plugin Serverless: Load command plugin:uninstall Serverless: Load command plugin Serverless: Load command plugin:list Serverless: Load command plugin Serverless: Load command plugin:search Serverless: Load command config Serverless: Load command config:credentials Serverless: Load command rollback Serverless: Load command rollback:function Serverless: Invoke deploy Serverless: Invoke package Serverless: Invoke aws:common:validate Serverless: Invoke aws:common:cleanupTempDir Serverless: Packaging service... Serverless: Excluding development dependencies... Type Error --------------------------------------------- Cannot read property 'replace' of undefined For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable. Stack Trace -------------------------------------------- TypeError: Cannot read property 'replace' of undefined at Object.normalizeNameToAlphaNumericOnly (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/lib/naming.js:32:36) at Object.getStreamLogicalId (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/lib/naming.js:236:13) at functionObj.events.forEach.event (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/stream/index.js:119:16) at Array.forEach (<anonymous>) at serverless.service.getAllFunctions.forEach (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/stream/index.js:41:28) at Array.forEach (<anonymous>) at AwsCompileStreamEvents.compileStreamEvents (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/stream/index.js:16:47) at BbPromise.reduce (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55) From previous event: at PluginManager.invoke (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22) at PluginManager.spawn (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:408:17) at Deploy.BbPromise.bind.then.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:123:50) From previous event: at Object.before:deploy:deploy [as hook] (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:113:10) at BbPromise.reduce (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55) From previous event: at PluginManager.invoke (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22) at PluginManager.run (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:421:17) at variables.populateService.then.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/Serverless.js:157:33) at runCallback (timers.js:810:20) at tryOnImmediate (timers.js:768:5) at processImmediate [as _immediateCallback] (timers.js:745:5) From previous event: at Serverless.run (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/Serverless.js:144:8) at serverless.init.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/bin/serverless:43:50) at <anonymous> Get Support -------------------------------------------- Docs: docs.serverless.com Bugs: github.com/serverless/serverless/issues Issues: forum.serverless.com Your Environment Information ----------------------------- OS: linux Node Version: 8.12.0 Serverless Version: 1.32.0
region.toLowerCase is not a function
$ serverless deploy -verbose Type Error --------------------------------------------- region.toLowerCase is not a function For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable. Get Support -------------------------------------------- Docs: docs.serverless.com Bugs: github.com/serverless/serverless/issues Issues: forum.serverless.com Your Environment Information ----------------------------- OS: linux Node Version: 8.12.0 Serverless Version: 1.32.0
デバッグをしてみる
$ SLS_DEBUG=* serverless deploy -verbose Serverless: Load command config Serverless: Load command config:credentials Serverless: Load command create Serverless: Load command install Serverless: Load command package Serverless: Load command deploy Serverless: Load command deploy:function Serverless: Load command deploy:list Serverless: Load command deploy:list:functions Serverless: Load command invoke Serverless: Load command invoke:local Serverless: Load command info Serverless: Load command logs Serverless: Load command login Serverless: Load command logout Serverless: Load command metrics Serverless: Load command print Serverless: Load command remove Serverless: Load command rollback Serverless: Load command rollback:function Serverless: Load command slstats Serverless: Load command plugin Serverless: Load command plugin Serverless: Load command plugin:install Serverless: Load command plugin Serverless: Load command plugin:uninstall Serverless: Load command plugin Serverless: Load command plugin:list Serverless: Load command plugin Serverless: Load command plugin:search Serverless: Load command config Serverless: Load command config:credentials Serverless: Load command rollback Serverless: Load command rollback:function Serverless: Invoke deploy Serverless: Invoke package Serverless: Invoke aws:common:validate Serverless: Invoke aws:common:cleanupTempDir Type Error --------------------------------------------- region.toLowerCase is not a function For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable. Stack Trace -------------------------------------------- TypeError: region.toLowerCase is not a function at getS3EndpointForRegion (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/utils/getS3EndpointForRegion.js:4:28) at AwsProvider.isS3TransferAccelerationSupported (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:335:22) at AwsPackage.generateCoreTemplate (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/lib/generateCoreTemplate.js:27:61) From previous event: at Object.package:initialize [as hook] (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/index.js:60:10) at BbPromise.reduce (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55) From previous event: at PluginManager.invoke (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22) at PluginManager.spawn (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:408:17) at Deploy.BbPromise.bind.then.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:123:50) From previous event: at Object.before:deploy:deploy [as hook] (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:113:10) at BbPromise.reduce (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55) From previous event: at PluginManager.invoke (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22) at PluginManager.run (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:421:17) at variables.populateService.then.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/Serverless.js:157:33) at runCallback (timers.js:810:20) at tryOnImmediate (timers.js:768:5) at processImmediate [as _immediateCallback] (timers.js:745:5) From previous event: at Serverless.run (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/Serverless.js:144:8) at serverless.init.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/bin/serverless:43:50) at <anonymous> Get Support -------------------------------------------- Docs: docs.serverless.com Bugs: github.com/serverless/serverless/issues Issues: forum.serverless.com Your Environment Information ----------------------------- OS: linux Node Version: 8.12.0 Serverless Version: 1.32.0