トリガーから起動されているフローの実行権限



+ [Record trigger flow is not running in system context.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007epjEzSAI)

>レコード トリガー フローはシステム コンテキストで実行されていません。フロー API バージョンは 61 で、レコード トリガー フローです。それでもシステム コンテキストでは実行されていません。フィールドの編集アクセスを削除すると、フローはフィールドを更新しません。 


確かにトリガーから起動されているように思う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/bf9a6d56-78ed-8589-8e96-16b267b91735.png)

:::note

レコードの更新を制限するトリガーが更新前にあります。プロファイル レベルでフィールドへの編集アクセス権を付与し、検証ルールを通じて要件を満たしました。

以下に解説がある
https://www.salto.io/blog-posts/salesforce-cannot-insert-update-activate-entity

:::


+ [Understanding Flow Run Context in Salesforce](https://www.linkedin.com/pulse/understanding-flow-run-context-salesforce-kfxof)


+ [【ヘルプ】Flow Run Context](https://help.salesforce.com/s/articleView?id=sf.flow_distribute_context.htm&type=5)

+ [Do record-trigger flows run as the system user?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000FVrq1SAD)

# Apex

+ [with sharing、without sharing、および inherited sharing キーワードの使用](https://developer.salesforce.com/docs/atlas.ja-jp.apexcode.meta/apexcode/apex_classes_keywords_sharing.htm)

### With Sharing
現在のユーザーの共有ルールを強制実行するには、クラスの宣言時に with sharing キーワードを使用します。このキーワードを明示的に設定すると、現在のユーザーコンテキストで Apex コードが実行されます。executeAnonymous コールで実行された Apex コードと Connect in Apex は、常に現在のユーザーの共有ルールを使用して実行されます。

### Without Sharing
現在のユーザーに適用されている共有ルールを強制実行されないようにするには、クラスの宣言時に without sharing キーワードを使用します。たとえば、クラスが with sharing を使用して宣言された別のクラスからコールされた場合、共有ルールの強制実行を明示的にオフにできます。


# Salesforce の「更新を挿入できません」エラーの謎を解く

+ [Demystifying “cannot insert update” errors in Salesforce](https://www.salto.io/blog-posts/salesforce-cannot-insert-update-activate-entity)


Apex でしばらく開発を行っている場合、恐ろしいエラーCANNOT_INSERT_UPDATE_ACTIVATE_ENTITY
に遭遇したことがあると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2670db5a-11e6-1c87-0adf-228f8ed7af07.png)


この投稿では、このエラー コードの意味、いつ発生するか、調査方法 (単一の修正方法はないことがわかります) について説明します。

### エンティティを挿入、更新、アクティブ化できません
簡単に言うと、このエラーは、Salesforce レコードを挿入または更新しようとしたときに問題が発生したため、レコードがデータベースにコミットされなかったことを意味します。

‍ 単語ごとに分解してみましょうENTITY )などのレコードを挿入、更新、またはアクティブ化 ( INSERT、UPDATE、ACTIVATE )できなかった ( CANNOT ) と伝えています。このコンテキストでACTIVATE が何を意味するのかはわかりませんが、 INSERTとUPDATE がレコードを作成または更新するプロセスを指していることは明らかです。これらすべてをまとめると、 CANNOT_INSERT_UPDATE_ACTIVATE_ENTITYとなり、アンダースコアは各単語間のスペースを表します。

### これが起こると
このエラーは主に Apex トリガーで問題が発生したときに発生しますが、すべてのトリガー失敗でこの特定のエラー メッセージが表示されるわけではありません。いくつかの例を見てみましょう (これらはすべて Account トリガーのコンテキスト内です)。‍ ‍ 数学的エラー‍ トリガー ハンドラー クラスに次のコードがあると。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/854dc819-e38b-3d37-eb7d-ad12b003f6cb.png)


このトリガーが実行されると、数値をゼロで割ることができないため、UI に次のエラーが表示されます。‍

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/99631034-275a-25df-0308-30ad363e1006.png)


トリガーでエラーが発生しても、CANNOT_INSERT_UPDATE_ACTIVATE_ENTITYエラーではなく MathException が発生することに注意してください。

‍ フィールド検証エラー

‍ 次のバージョンのコードを試してみましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/40822451-2ca8-a1d2-f114-cc86a35e092f.png)


ここでは、空の取引先責任者レコードを挿入しようとしていますが、必須フィールド ( LastNameなど)に値を指定していないため、失敗するはずです。このコードを実行すると、次のようになります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/0892adb7-1aaa-24ca-0e92-dfa49fe3c1d9.png)


さて、まだ悪名高いエラーは見ていません。インフラストラクチャエラー

をトリガーする最後に、コードの3番目のバージョンで何が起こるか見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/28004512-d893-1cd9-0b19-dd8a7e9a4ccd.png)


今回は、空の取引先レコードを作成します。前のセクションでは、取引先担当者に対してこれを行いました。取引先担当者の場合と同様に、検証エラーで失敗すると予想していましたが、なんと、実際にはCANNOT_INSERT_UPDATE_ACTIVATE_ENTITYエラーが発生しています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/483f3282-164e-e697-52d7-9392de574f4d.png)


皆さんはどうか分かりませんが、私はこのエラーを見てこんなにうれしかったことはありません。空の取引先を挿入するとき ( new Account()   ) にはこのエラーが表示されるのに、空の取引先責任者を挿入するとき ( new Contact() )には表示されないのはなぜでしょうか。その理由は、 new Account()を呼び出すと、すでに before insert トリガーのコンテキスト内にあり、new Account()を呼び出すと、必須フィールドが評価される前に新しいトリガー実行が作成されるためです。**Salesforceの実行順序を見ると、システム検証ルール (必須フィールドが入力されていることを確認するなど) は、before トリガーが実行された後にのみ実行されることがわかります。**


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e0ae1c98-b830-1b81-378a-18a633ba35ff.png)


ここで何が起こっているかというと、取引先レコードが挿入されると、別のレコードが作成され、同じトリガーが起動して別のレコードが作成され、これが繰り返されるという具合です。ステップ 5 に進む機会はありません。ステップ 1 と 4 の間でループしています。

この結果、トリガーはトリガーの最大深度制限に達するまで繰り返し実行されます。

‍ new Contact()の場合、同じトランザクションに他の取引先責任者を挿入する取引先責任者のトリガーがないため、エラーが異なります。そのため、ステップ 5 に進み、LastNameフィールドが必須であることを示すエラーが表示されます。

ソースは誤って構成されたトリガーであり、レコード自体に問題があるわけではないため、私はこれをトリガーインフラストラクチャの障害と呼んでいます。

とはいえ、このエラーがトリガーインフラストラクチャの障害にのみ発生すると 100% 確信を持って言うことはできないと思います。この種の他の障害ではこのエラーは発生しないためです。たとえば、次のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/d3b5a8cf-e75c-36b9-4bdd-5c9bbf004850.png)

ここで行っているのは、トリガーによって処理されているのと同じアカウントを更新することです。これにより、次のエラーが発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b404e6a6-2843-e0d9-d950-53984fb8420e.png)


ここでSELF_REFERENCE_FROM_TRIGGERエラーが発生します。これは基本的に、 beforeUpdateトリガー内のトリガーでレコードを更新できないことを意味します。

これはトリガー インフラストラクチャ エラーであると考えられますが、CANNOT_INSERT_UPDATE_ACTIVATE_ENTITYエラーは表示されません。なぜでしょうか? これについては Salesforce に問い合わせる必要があります。:)

‍ プロセスビルダーとフロー

‍ 最後に、トリガーの実行中にフロー/プロセスが失敗した場合にもこのエラーがスローされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/42544d6f-5f1c-9821-6976-329261b48cc8.png)


ここで、エラー メッセージは、トリガー実行中にProcess Updating Field

というプロセスまたはフローが失敗したことを示しています。したがって、Salesforce が次の 2 つのシナリオでエラーをスローする可能性があることがわかります。

+ 再帰トリガーの失敗
+ プロセスとフローの障害


### どうやって取り除くか
このエラーがいつ発生するかがわかったので、次はこのエラーを解消する方法について説明します。‍ 再帰の制御‍ 最初の部分は、トリガー ハンドラーを再帰的に制御できるようにすることです。これは基本的に、単一のトランザクションで同じトリガーが何回実行されるかを制御できる必要があることを意味します。大まかに言えば、トリガーがすでに実行されたかどうかを判断できるトリガー内の静的変数を使用することでこれを制御できます。次に簡単な例を示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/72a7a934-f888-a4c1-e299-4a7eaf955ba6.png)


とはいえ、これを実装するにはApex トリガーフレームワークを使用するのが最適です。たとえば、Kevin O'Hara のトリガーフレームワークを使用すると、トリガーを実行できる回数を指定できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9471799f-39e3-c513-3aec-680c4d082ed6.png)


これにより、単純な静的変数を使用するよりもはるかに柔軟性が高まります。

‍ プロセスとフロー

‍ 2番目try/catchブロックでラップするようにしてください

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b6da8b48-12bd-ddfe-4dc8-bed4701bcdca.png)

以上です。これでこの厄介なエラーを解消できたことを願っています。