{"componentChunkName":"component---src-templates-blog-post-js","path":"/blog/power-automate-tratamento-erros-scope-try-catch/","result":{"data":{"markdownRemark":{"frontmatter":{"title":"Power Automate: tratamento de erros com scopes e Try-Catch-Finally","description":"Fluxos corporativos falham em silêncio sem uma estratégia de erros. Veja como aplicar o padrão Try-Catch-Finally com scopes, retry policies e notificações no Power Automate.","date":"20 de julho de 2026","thumbnail":null},"html":"<p>Em ambientes de produção, o que separa uma automação amadora de uma automação corporativa raramente é a lógica de negócio — é o tratamento de erros. Um fluxo que funciona no happy path mas falha em silêncio quando uma API retorna 429 ou um registro não existe no Dataverse é uma bomba-relógio. Neste post, mostramos como estruturar tratamento de erros robusto no Power Automate usando o padrão Try-Catch-Finally com scopes, configurações de run after e retry policies.</p>\n<p><strong>Por que o comportamento padrão não é suficiente</strong></p>\n<p>Por padrão, quando uma ação falha no Power Automate, o fluxo inteiro para e é marcado como <em>Failed</em>. Isso pode ser aceitável em automações simples, mas em fluxos críticos — integrações financeiras, provisionamento de usuários, sincronização entre sistemas — parar sem registrar o que aconteceu, sem notificar ninguém e sem desfazer estados parciais é inaceitável.</p>\n<p>O problema é que muitos desenvolvedores tratam erro ação por ação, com dezenas de branches <em>Configure run after</em> espalhados. Isso vira um pesadelo de manutenção. A abordagem escalável é isolar blocos lógicos em scopes e centralizar o tratamento.</p>\n<p><strong>O padrão Try-Catch-Finally com scopes</strong></p>\n<p>Um <em>Scope</em> no Power Automate agrupa ações e propaga o status agregado do bloco (Succeeded, Failed, Skipped, TimedOut). A partir disso, você monta três scopes principais:</p>\n<ol>\n<li><strong>Try</strong> — contém toda a lógica de negócio principal (chamadas de API, operações Dataverse, cálculos).</li>\n<li><strong>Catch</strong> — configurado com <em>Configure run after</em> para rodar apenas quando o scope Try tiver status <strong>has failed</strong>, <strong>is skipped</strong> ou <strong>has timed out</strong>. Aqui você registra o erro, notifica e faz rollback.</li>\n<li><strong>Finally</strong> — configurado para rodar <strong>is successful</strong>, <strong>has failed</strong>, <strong>is skipped</strong> e <strong>has timed out</strong> do Catch, garantindo que sempre execute (limpeza, log de encerramento, atualização de status).</li>\n</ol>\n<p>Essa estrutura reproduz o try/catch/finally de linguagens tradicionais e mantém o fluxo legível mesmo com dezenas de ações dentro do Try.</p>\n<p><strong>Como capturar o detalhe do erro que realmente falhou</strong></p>\n<p>Dentro do Catch, a mágica está na função <code>result()</code>. Ao usar <code>result('Try')</code> você obtém um array com o resultado de cada ação executada dentro do scope Try, incluindo status, código e mensagem de erro. Combinado com um <em>Filter array</em> que seleciona apenas os itens com <code>status</code> igual a <code>Failed</code>, você extrai exatamente qual ação quebrou e por quê — sem adivinhação.</p>\n<p>Uma expressão útil para o corpo da notificação:</p>\n<ul>\n<li><code>body('Filtrar_falhas')</code> para listar todas as ações falhas;</li>\n<li><code>first(body('Filtrar_falhas'))?['error']?['message']</code> para pegar a mensagem da primeira falha;</li>\n<li><code>workflow()?['run']?['name']</code> para incluir o Run ID e facilitar o rastreamento no histórico.</li>\n</ul>\n<p><strong>Retry policies: antes de cair no Catch</strong></p>\n<p>Muitos erros são transitórios — throttling (429), timeouts de rede, indisponibilidade momentânea de serviço. Não faz sentido acionar o Catch e o rollback para uma falha que se resolveria com uma nova tentativa. Cada ação HTTP e vários conectores têm, em <em>Settings</em>, a configuração de <strong>Retry Policy</strong>:</p>\n<ul>\n<li><strong>Default</strong> — até 4 tentativas com backoff exponencial;</li>\n<li><strong>Exponential Interval</strong> — permite ajustar o intervalo mínimo, máximo e a contagem de retries;</li>\n<li><strong>Fixed Interval</strong> — intervalo fixo, útil para APIs com limites bem definidos;</li>\n<li><strong>None</strong> — desativa retries, indicado quando a operação não é idempotente e uma repetição causaria efeito colateral (ex.: cobrar um cartão duas vezes).</li>\n</ul>\n<p>A regra prática: use retry para falhas transitórias e reserve o Catch para falhas reais de negócio ou erros permanentes.</p>\n<p><strong>Idempotência e rollback no Catch</strong></p>\n<p>O ponto mais negligenciado é o estado parcial. Se seu Try criou um registro no Dataverse, chamou uma API externa e então falhou na terceira ação, o Catch precisa desfazer o que foi feito para não deixar dados inconsistentes. Estratégias:</p>\n<ul>\n<li>Registre em variáveis os IDs criados durante o Try, para poder deletá-los ou reverter no Catch;</li>\n<li>Prefira operações idempotentes (upsert com chave alternativa no Dataverse em vez de create cego);</li>\n<li>Para integrações críticas, considere um padrão de <em>compensating transaction</em>, onde cada passo tem uma ação inversa correspondente.</li>\n</ul>\n<p><strong>Notificação e observabilidade</strong></p>\n<p>Um fluxo crítico que falha e ninguém fica sabendo é tão ruim quanto não ter fluxo. No Catch, além do log, envie uma notificação acionável — um card no Teams com o nome do fluxo, o Run ID, a ação que falhou e um link direto para o histórico de execução. Para volumes maiores, grave os erros em uma tabela Dataverse dedicada e construa um relatório no Power BI para identificar padrões de falha e reincidência.</p>\n<p><strong>Boas práticas para escalar</strong></p>\n<ul>\n<li>Padronize o Try-Catch-Finally como template e reutilize-o via child flows (assunto que já cobrimos no blog);</li>\n<li>Nunca deixe o Catch falhar silenciosamente — teste-o forçando exceções propositais em homologação;</li>\n<li>Documente quais erros são recuperáveis (retry) e quais exigem intervenção manual;</li>\n<li>Combine com environment variables para parametrizar destinatários de notificação entre Dev/Test/Prod.</li>\n</ul>\n<p>Tratamento de erros bem-feito é o que transforma uma prova de conceito em uma automação de produção confiável. Se sua empresa depende de fluxos críticos no Power Automate e precisa de arquitetura resiliente, governança e monitoramento contínuo, a Dynamic Soluções pode ajudar — seja por meio dos nossos planos de suporte ou do portal Self-Service de Power Platform, que une IA e especialistas humanos para entregar soluções mais rápido e com padrão corporativo.</p>\n<p>In production environments, what separates an amateur automation from an enterprise-grade one is rarely the business logic — it's error handling. A flow that works on the happy path but fails silently when an API returns 429 or a record doesn't exist in Dataverse is a ticking time bomb. In this post, we show how to structure robust error handling in Power Automate using the Try-Catch-Finally pattern with scopes, run after settings, and retry policies.</p>\n<p><strong>Why the default behavior isn't enough</strong></p>\n<p>By default, when an action fails in Power Automate, the entire flow stops and is marked as <em>Failed</em>. That may be acceptable in simple automations, but in critical flows — financial integrations, user provisioning, cross-system synchronization — stopping without logging what happened, without notifying anyone, and without undoing partial states is unacceptable.</p>\n<p>The problem is that many developers handle errors action by action, with dozens of <em>Configure run after</em> branches scattered around. This becomes a maintenance nightmare. The scalable approach is to isolate logical blocks into scopes and centralize the handling.</p>\n<p><strong>The Try-Catch-Finally pattern with scopes</strong></p>\n<p>A <em>Scope</em> in Power Automate groups actions and propagates the aggregate status of the block (Succeeded, Failed, Skipped, TimedOut). From that, you build three main scopes:</p>\n<ol>\n<li><strong>Try</strong> — contains all the main business logic (API calls, Dataverse operations, calculations).</li>\n<li><strong>Catch</strong> — configured with <em>Configure run after</em> to run only when the Try scope status is <strong>has failed</strong>, <strong>is skipped</strong>, or <strong>has timed out</strong>. Here you log the error, notify, and roll back.</li>\n<li><strong>Finally</strong> — configured to run on <strong>is successful</strong>, <strong>has failed</strong>, <strong>is skipped</strong>, and <strong>has timed out</strong> of the Catch, ensuring it always executes (cleanup, closing log, status update).</li>\n</ol>\n<p>This structure reproduces the try/catch/finally of traditional languages and keeps the flow readable even with dozens of actions inside the Try.</p>\n<p><strong>How to capture the detail of the action that actually failed</strong></p>\n<p>Inside the Catch, the magic lies in the <code>result()</code> function. Using <code>result('Try')</code> gives you an array with the outcome of each action executed inside the Try scope, including status, code, and error message. Combined with a <em>Filter array</em> that selects only items with <code>status</code> equal to <code>Failed</code>, you extract exactly which action broke and why — no guessing.</p>\n<p>Useful expressions for the notification body:</p>\n<ul>\n<li><code>body('Filter_failures')</code> to list all failed actions;</li>\n<li><code>first(body('Filter_failures'))?['error']?['message']</code> to grab the message of the first failure;</li>\n<li><code>workflow()?['run']?['name']</code> to include the Run ID and make tracing in the history easier.</li>\n</ul>\n<p><strong>Retry policies: before falling into the Catch</strong></p>\n<p>Many errors are transient — throttling (429), network timeouts, momentary service unavailability. It makes no sense to trigger the Catch and rollback for a failure that would resolve itself with a retry. Each HTTP action and several connectors have, under <em>Settings</em>, a <strong>Retry Policy</strong> configuration:</p>\n<ul>\n<li><strong>Default</strong> — up to 4 attempts with exponential backoff;</li>\n<li><strong>Exponential Interval</strong> — lets you adjust the minimum, maximum interval, and retry count;</li>\n<li><strong>Fixed Interval</strong> — fixed interval, useful for APIs with well-defined limits;</li>\n<li><strong>None</strong> — disables retries, recommended when the operation is not idempotent and repeating it would cause a side effect (e.g., charging a card twice).</li>\n</ul>\n<p>The rule of thumb: use retry for transient failures and reserve the Catch for real business failures or permanent errors.</p>\n<p><strong>Idempotency and rollback in the Catch</strong></p>\n<p>The most overlooked point is partial state. If your Try created a Dataverse record, called an external API, and then failed on the third action, the Catch needs to undo what was done to avoid leaving inconsistent data. Strategies:</p>\n<ul>\n<li>Store the IDs created during the Try in variables so you can delete them or revert in the Catch;</li>\n<li>Prefer idempotent operations (upsert with an alternate key in Dataverse instead of a blind create);</li>\n<li>For critical integrations, consider a <em>compensating transaction</em> pattern, where each step has a corresponding inverse action.</li>\n</ul>\n<p><strong>Notification and observability</strong></p>\n<p>A critical flow that fails and no one finds out is as bad as having no flow at all. In the Catch, beyond logging, send an actionable notification — a Teams card with the flow name, the Run ID, the action that failed, and a direct link to the run history. For larger volumes, record errors in a dedicated Dataverse table and build a Power BI report to identify failure patterns and recurrence.</p>\n<p><strong>Best practices to scale</strong></p>\n<ul>\n<li>Standardize Try-Catch-Finally as a template and reuse it via child flows (a topic we've already covered on the blog);</li>\n<li>Never let the Catch fail silently — test it by forcing intentional exceptions in staging;</li>\n<li>Document which errors are recoverable (retry) and which require manual intervention;</li>\n<li>Combine it with environment variables to parameterize notification recipients across Dev/Test/Prod.</li>\n</ul>\n<p>Proper error handling is what turns a proof of concept into a reliable production automation. If your company depends on critical Power Automate flows and needs resilient architecture, governance, and continuous monitoring, Dynamic Soluções can help — whether through our support plans or the Power Platform Self-Service portal, which combines AI and human experts to deliver solutions faster and to an enterprise standard.</p>"}},"pageContext":{"slug":"/blog/power-automate-tratamento-erros-scope-try-catch/","previousPost":null,"nextPost":{"frontmatter":{"title":"Copilot Studio: agentes conectados ao Dataverse na prática"},"fields":{"slug":"/blog/copilot-studio-agentes-dataverse-topicos-actions/"}}}},"staticQueryHashes":["2269431855"]}