Answers.Body: <p>Ok so with these the trick is to look for anything that might involve a request session, which is not available when you're running things via a console request.</p>
  <p>In this case there's at least one obvious suspect line:</p>
  <p><code>Craft::$app-&gt;session-&gt;setError('Lightspeed....);</code></p>
  <p>Indeed there's more than one of these.</p>
  <p>It's basically the same problem as previously - i.e. if there's no session, then you can't set errors on the session (or retrieve a cart from the session).</p>
  <p>So you might need to check if the current request is a console request (if this code is ever run in a non console way) ... And deal with errors differently if so.</p>
  <pre class="lang-php prettyprint-override"><code>if (Craft::$app-&gt;getRequest()-&gt;getIsConsoleRequest()) {
     ...send errors to a log file, email an alert, ....
  }
  </code></pre>
  <p>(As to why this is running as a console request - it depends how it is called.  E.g. you're explicitly running it from the console, or your queue runner is doing so....)</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-10-01T21:38:31.610Z
Answers.LastActivityDate: 2020-10-01T22:31:20.000Z
Answers.LastEditDate: 2020-10-01T22:31:20.000Z
Answers.UserDisplayName: Jeremy Daalder
Body: <p>I already experienced this same problem with Craft Commerce a while ago (<a href="https://craftcms.stackexchange.com/questions/35920/error-on-functions-in-queue-session-does-not-exist-in-a-console-request">Error on functions in queue: &quot;Session does not exist in a console request.&quot;</a>) and got a solution that solved the problem for the function described in that question, but this time the problem occurs on a different function and I can't seem to find a solution.</p>
  <p>There's a connection with the Lightspeed API to update product stock values every 15 minutes and to import new products. These are all handled by the queue and work most of the time, but sometimes it throws an error saying &quot;<strong>Session does not exist in a console request</strong>&quot;
  <a href="https://i.sstatic.net/nkbfz.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/nkbfz.png" alt="Queue manager screenshot" /></a></p>
  <p>Here are all functions that are performed in this action (I know it's a lot, but I am getting quite desperate):</p>
  <p><em>Controller action</em></p>
  <pre><code>public function actionImportNewProducts()
  {
      Stock::$plugin-&gt;lightspeedService-&gt;refreshToken();
      
      $allowedCategories = Craft::$app-&gt;request-&gt;getBodyParam('categories');
  
      $startParam = Craft::$app-&gt;request-&gt;getBodyParam('startDate');
      $startDate = new \DateTime($startParam['date']);
  
      $endParam = Craft::$app-&gt;request-&gt;getBodyParam('endDate');
      if (!$endParam) {
          $endDate = new \DateTime();
      } else {
          $endDate = new \DateTime($endParam['date']);
      }
      $endDate = $endDate-&gt;modify('tomorrow midnight');
  
      $limit = 100;
      $pages = Stock::$plugin-&gt;lightspeedService-&gt;getPagination();
      $productCount = 0;
  
      for ($page = 0; $page &lt; $pages; $page++) {
          $offset = $page * $limit;
          $inventory = json_decode(Stock::$plugin-&gt;lightspeedService-&gt;getInventory($offset, '[&quot;ItemShops&quot;, &quot;Category&quot;, &quot;TaxClass&quot;]'), true);
  
          $items = $inventory['Item'];
          foreach ($items as $item) {
              $createdAt = new \DateTime($item['createTime']);
              $createdAt = $createdAt-&gt;modify('midnight');
  
              if ($createdAt &gt;= $startDate &amp;&amp; $createdAt &lt;= $endDate) {
                  $category = $item['Category'];
                  if (in_array($category['categoryID'], $allowedCategories)) {
                      if (!$item['archived'] or $item['archived'] == 'false') {
                          Stock::$plugin-&gt;productService-&gt;queueImportProduct($item);
                          $productCount++;
                      }
                  }
              }
          }
      }
  
      Craft::$app-&gt;session-&gt;setNotice($productCount . ' producten aan het importeren.');
  }
  </code></pre>
  <p><em>LightspeedService refreshToken</em></p>
  <pre><code>public function refreshToken()
  {
      $refreshToken = Stock::getInstance()-&gt;settings-&gt;refreshToken;
      if (!$refreshToken) {
          Craft::$app-&gt;session-&gt;setError('Lightspeed refreshtoken ontbreekt');
          return false;
      }
  
      $client = new GuzzleClient();
      $url = 'https://cloud.lightspeedapp.com/oauth/access_token.php';
      $body['multipart'] = [
          [
              'name'     =&gt; 'client_id',
              'contents' =&gt; getenv('LIGHTSPEED_CLIENT_ID')
          ],
          [
              'name'     =&gt; 'client_secret',
              'contents' =&gt; getenv('LIGHTSPEED_CLIENT_SECRET')
          ],
          [
              'name'     =&gt; 'refresh_token',
              'contents' =&gt; $refreshToken
          ],
          [
              'name'     =&gt; 'grant_type',
              'contents' =&gt; 'refresh_token'
          ]
      ];
  
      try {
          $request = $client-&gt;request('POST', $url, $body);
          $response = $request-&gt;getBody()-&gt;getContents();
          $response = json_decode($response);
  
          $accessToken = $response-&gt;access_token;
  
          if (!$accessToken) {
              return $this-&gt;asJson($response);
          }
  
          $settings['accessToken'] = $accessToken;
          $plugin = Craft::$app-&gt;getPlugins()-&gt;getPlugin('stock');
          Craft::$app-&gt;getPlugins()-&gt;savePluginSettings($plugin, $settings);
  
          return $response;
      } catch (ClientException $e) {
          return $e-&gt;getMessage();
      }
  }
  </code></pre>
  <p><em>LightspeedService getPagination</em></p>
  <pre><code>public function getPagination()
  {
      $inventory = json_decode(Stock::$plugin-&gt;lightspeedService-&gt;getInventory(), true);
      $attributes = $inventory['@attributes'];
  
      $count = intval($attributes['count']);
      $limit = intval($attributes['limit']);
  
      return ceil($count / $limit);
  }
  </code></pre>
  <p><em>LightspeedService getInventory</em></p>
  <pre><code>public function getInventory($offset = 0, $relations = null)
  {
      Stock::$plugin-&gt;lightspeedService-&gt;refreshToken();
      
      $client = new GuzzleClient();
      $url = getenv('LIGHTSPEED_API_URL') . '/API/Account/' . getenv('LIGHTSPEED_ACCOUNT_ID') . '/Item.json?offset=' . $offset;
      if ($relations) {
          $url = $url . &quot;&amp;load_relations={$relations}&quot;;
      }
  
      $headers = [
          'Authorization' =&gt; 'Bearer ' . Stock::getInstance()-&gt;settings-&gt;accessToken
      ];
  
      try {
          $request = $client-&gt;request('GET', $url, [
              'headers' =&gt; $headers
          ]);
          $response = $request-&gt;getBody()-&gt;getContents();
          return $response;
      } catch (ClientException $e) {
          return $e-&gt;getMessage();
      }
  }
  </code></pre>
  <p><em>ProductService queueImportProduct</em></p>
  <pre><code>public function queueImportProduct($item)
  {
      Craft::$app-&gt;queue-&gt;push(new ImportProduct([
          'item' =&gt; $item
      ]));
  }
  </code></pre>
  <p><em>Job importProduct</em></p>
  <pre><code>public function execute($queue)
  {
      Stock::$plugin-&gt;productService-&gt;importProduct($this-&gt;item);
  }
  </code></pre>
  <p><em>ProductService importProduct</em></p>
  <p><em>I had read in another question that it could help to replace all product updates by DB queries, but that didn't solve my problem.</em></p>
  <pre><code>public function importProduct($item)
  {
      $sku = $item['systemSku'];
      $price = Stock::$plugin-&gt;lightspeedService-&gt;getDefaultPrice($item);
      $stock = Stock::$plugin-&gt;lightspeedService-&gt;getItemQoh($item);
      $productTypeId = Stock::$plugin-&gt;productService-&gt;getProductType($item['Category']);
      $taxCategoryId = Stock::$plugin-&gt;lightspeedService-&gt;getTaxCategoryId($item['TaxClass']['taxClassID']);
      $variant = Variant::find()-&gt;sku($sku)-&gt;one();
  
      if (!$variant) {
          $product = new Product();
          $product-&gt;typeId = $productTypeId;
          $product-&gt;enabled = false;
          $product-&gt;title = $item['description'];
          $product-&gt;promotable = true;
          $product-&gt;taxCategoryId = $taxCategoryId;
          
          $variant = new Variant();
          $variant-&gt;isDefault = true;
  
          $variant-&gt;sku = $sku;
          $variant-&gt;price = (float) $price;
          $variant-&gt;stock = $stock;
  
          $product-&gt;setVariants([$variant]);
          Craft::$app-&gt;elements-&gt;saveElement($product);
      } else {
          $product = $variant-&gt;product;
  
          Craft::$app-&gt;getDb()-&gt;createCommand()-&gt;update('{{%commerce_products}}',
              [
                  'taxCategoryId' =&gt; $taxCategoryId,
              ],
              [
                  'id' =&gt; $variant-&gt;product-&gt;id
              ]
          )-&gt;execute();
  
          Craft::$app-&gt;getDb()-&gt;createCommand()-&gt;update('{{%commerce_variants}}',
              [
                  'sku' =&gt; $sku,
                  'price' =&gt; (float) $price,
                  'stock' =&gt; $stock
              ],
              [
                  'id' =&gt; $variant-&gt;id
              ]
          )-&gt;execute();
      }
  
      $lightspeedProductRecord = LightspeedProductsRecord::findOne(['itemId' =&gt; $item['itemID']]);
      if (!$lightspeedProductRecord) {
          $lightspeedProductRecord = new LightspeedProductsRecord();
          $lightspeedProductRecord-&gt;itemId = $item['itemID'];
      }
  
      $lightspeedProductRecord-&gt;variantId = $variant-&gt;id;
      $lightspeedProductRecord-&gt;save();
  }
  </code></pre>
  <p><strong>Any help will be appreciated!</strong></p>
  
Tags: <craft3><plugin-craftcommerce><error><queue>
Title: Error on functions in queue: “Session does not exist in a console request.”
ThreadText: # Error on functions in queue: “Session does not exist in a console request.”
  
  (Asked by: username_0 on 2020-10-01)
  
  I already experienced this same problem with Craft Commerce a while ago ([Error on functions in queue: "Session does not exist in a console request."](https://craftcms.stackexchange.com/questions/35920/error-on-functions-in-queue-session-does-not-exist-in-a-console-request)) and got a solution that solved the problem for the function described in that question, but this time the problem occurs on a different function and I can't seem to find a solution.
  
  There's a connection with the Lightspeed API to update product stock values every 15 minutes and to import new products. These are all handled by the queue and work most of the time, but sometimes it throws an error saying "**Session does not exist in a console request**"
  [![Queue manager screenshot](https://i.sstatic.net/nkbfz.png)](https://i.sstatic.net/nkbfz.png)
  
  Here are all functions that are performed in this action (I know it's a lot, but I am getting quite desperate):
  
  *Controller action*
  
  ```
  public function actionImportNewProducts()
  {
      Stock::$plugin->lightspeedService->refreshToken();
      
      $allowedCategories = Craft::$app->request->getBodyParam('categories');
  
      $startParam = Craft::$app->request->getBodyParam('startDate');
      $startDate = new \DateTime($startParam['date']);
  
      $endParam = Craft::$app->request->getBodyParam('endDate');
      if (!$endParam) {
          $endDate = new \DateTime();
      } else {
          $endDate = new \DateTime($endParam['date']);
      }
      $endDate = $endDate->modify('tomorrow midnight');
  
      $limit = 100;
      $pages = Stock::$plugin->lightspeedService->getPagination();
      $productCount = 0;
  
      for ($page = 0; $page < $pages; $page++) {
          $offset = $page * $limit;
          $inventory = json_decode(Stock::$plugin->lightspeedService->getInventory($offset, '["ItemShops", "Category", "TaxClass"]'), true);
  
          $items = $inventory['Item'];
          foreach ($items as $item) {
              $createdAt = new \DateTime($item['createTime']);
              $createdAt = $createdAt->modify('midnight');
  
              if ($createdAt >= $startDate && $createdAt <= $endDate) {
                  $category = $item['Category'];
                  if (in_array($category['categoryID'], $allowedCategories)) {
                      if (!$item['archived'] or $item['archived'] == 'false') {
                          Stock::$plugin->productService->queueImportProduct($item);
                          $productCount++;
                      }
                  }
              }
          }
      }
  
      Craft::$app->session->setNotice($productCount . ' producten aan het importeren.');
  }
  
  ```
  
  *LightspeedService refreshToken*
  
  ```
  public function refreshToken()
  {
      $refreshToken = Stock::getInstance()->settings->refreshToken;
      if (!$refreshToken) {
          Craft::$app->session->setError('Lightspeed refreshtoken ontbreekt');
          return false;
      }
  
      $client = new GuzzleClient();
      $url = 'https://cloud.lightspeedapp.com/oauth/access_token.php';
      $body['multipart'] = [
          [
              'name'     => 'client_id',
              'contents' => getenv('LIGHTSPEED_CLIENT_ID')
          ],
          [
              'name'     => 'client_secret',
              'contents' => getenv('LIGHTSPEED_CLIENT_SECRET')
          ],
          [
              'name'     => 'refresh_token',
              'contents' => $refreshToken
          ],
          [
              'name'     => 'grant_type',
              'contents' => 'refresh_token'
          ]
      ];
  
      try {
          $request = $client->request('POST', $url, $body);
          $response = $request->getBody()->getContents();
          $response = json_decode($response);
  
          $accessToken = $response->access_token;
  
          if (!$accessToken) {
              return $this->asJson($response);
          }
  
          $settings['accessToken'] = $accessToken;
          $plugin = Craft::$app->getPlugins()->getPlugin('stock');
          Craft::$app->getPlugins()->savePluginSettings($plugin, $settings);
  
          return $response;
      } catch (ClientException $e) {
          return $e->getMessage();
      }
  }
  
  ```
  
  *LightspeedService getPagination*
  
  ```
  public function getPagination()
  {
      $inventory = json_decode(Stock::$plugin->lightspeedService->getInventory(), true);
      $attributes = $inventory['@attributes'];
  
      $count = intval($attributes['count']);
      $limit = intval($attributes['limit']);
  
      return ceil($count / $limit);
  }
  
  ```
  
  *LightspeedService getInventory*
  
  ```
  public function getInventory($offset = 0, $relations = null)
  {
      Stock::$plugin->lightspeedService->refreshToken();
      
      $client = new GuzzleClient();
      $url = getenv('LIGHTSPEED_API_URL') . '/API/Account/' . getenv('LIGHTSPEED_ACCOUNT_ID') . '/Item.json?offset=' . $offset;
      if ($relations) {
          $url = $url . "&load_relations={$relations}";
      }
  
      $headers = [
          'Authorization' => 'Bearer ' . Stock::getInstance()->settings->accessToken
      ];
  
      try {
          $request = $client->request('GET', $url, [
              'headers' => $headers
          ]);
          $response = $request->getBody()->getContents();
          return $response;
      } catch (ClientException $e) {
          return $e->getMessage();
      }
  }
  
  ```
  
  *ProductService queueImportProduct*
  
  ```
  public function queueImportProduct($item)
  {
      Craft::$app->queue->push(new ImportProduct([
          'item' => $item
      ]));
  }
  
  ```
  
  *Job importProduct*
  
  ```
  public function execute($queue)
  {
      Stock::$plugin->productService->importProduct($this->item);
  }
  
  ```
  
  *ProductService importProduct*
  
  *I had read in another question that it could help to replace all product updates by DB queries, but that didn't solve my problem.*
  
  ```
  public function importProduct($item)
  {
      $sku = $item['systemSku'];
      $price = Stock::$plugin->lightspeedService->getDefaultPrice($item);
      $stock = Stock::$plugin->lightspeedService->getItemQoh($item);
      $productTypeId = Stock::$plugin->productService->getProductType($item['Category']);
      $taxCategoryId = Stock::$plugin->lightspeedService->getTaxCategoryId($item['TaxClass']['taxClassID']);
      $variant = Variant::find()->sku($sku)->one();
  
      if (!$variant) {
          $product = new Product();
          $product->typeId = $productTypeId;
          $product->enabled = false;
          $product->title = $item['description'];
          $product->promotable = true;
          $product->taxCategoryId = $taxCategoryId;
          
          $variant = new Variant();
          $variant->isDefault = true;
  
          $variant->sku = $sku;
          $variant->price = (float) $price;
          $variant->stock = $stock;
  
          $product->setVariants([$variant]);
          Craft::$app->elements->saveElement($product);
      } else {
          $product = $variant->product;
  
          Craft::$app->getDb()->createCommand()->update('{{%commerce_products}}',
              [
                  'taxCategoryId' => $taxCategoryId,
              ],
              [
                  'id' => $variant->product->id
              ]
          )->execute();
  
          Craft::$app->getDb()->createCommand()->update('{{%commerce_variants}}',
              [
                  'sku' => $sku,
                  'price' => (float) $price,
                  'stock' => $stock
              ],
              [
                  'id' => $variant->id
              ]
          )->execute();
      }
  
      $lightspeedProductRecord = LightspeedProductsRecord::findOne(['itemId' => $item['itemID']]);
      if (!$lightspeedProductRecord) {
          $lightspeedProductRecord = new LightspeedProductsRecord();
          $lightspeedProductRecord->itemId = $item['itemID'];
      }
  
      $lightspeedProductRecord->variantId = $variant->id;
      $lightspeedProductRecord->save();
  }
  
  ```
  
  **Any help will be appreciated!**
  
  **Tags:** craft3, plugin-craftcommerce, error, queue
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2020-10-01. Score: 3 | Accepted answer
  
  Ok so with these the trick is to look for anything that might involve a request session, which is not available when you're running things via a console request.
  
  In this case there's at least one obvious suspect line:
  
  `Craft::$app->session->setError('Lightspeed....);`
  
  Indeed there's more than one of these.
  
  It's basically the same problem as previously - i.e. if there's no session, then you can't set errors on the session (or retrieve a cart from the session).
  
  So you might need to check if the current request is a console request (if this code is ever run in a non console way) ... And deal with errors differently if so.
  
  ```php
  if (Craft::$app->getRequest()->getIsConsoleRequest()) {
     ...send errors to a log file, email an alert, ....
  }
  
  ```
  
  (As to why this is running as a console request - it depends how it is called. E.g. you're explicitly running it from the console, or your queue runner is doing so....)
  
  
  ---
  
  