Vue normale

Il y a de nouveaux articles disponibles, cliquez pour rafraîchir la page.
À partir d’avant-hierFlux principal

Fixing the `InvokerConnectionOverrideFailed` Error When a Power App Calls a Power Automate Flo

One of the cool things you can do from a canvas Power App is call a Power Automate flow. This is a great way to do something simple – like sending an email – or many more complex things you might want to trigger from the Power App. Many have written about how to implement these sorts of things, so I won’t cover that ground here.

Once you’ve got it set up and time goes by, your users may start to see an error message similar to this when they take the action to trigger the flow in the Power App. It might be a button click, changing a number in a field – it can really be anything where you can connect to an event in the Power App.

That’s:

{"code": "InvokerConnectionOverrideFailed", "message": "Failed to parse invoker connections from trigger 'manual' outputs. Exception: Could not find any valid connection for connection reference name 'shared_office365_1' in APIM tokens header."}

The contents of the error you see may be a little bit different, but every report I saw mentioned InvokerConnectionOverrideFailed.

This is a post which shouldn’t need to exist, in my opinion. Once we have the connection between the Power App and the Power Automate flow, it should just work going forward. But after some indeterminate amount of time has passed, you may start to see the error above. The two tools somehow lose their connection.

We had this happen at a client recently, so I went off to the InterWebs to see if I could find an answer. There are multiple posts about it with multiple answers. I’ll summarize the one I found that worked for me here.

In my particular case, the Power App enables event signups. Each event has one or more available time slots with a maximum number of registrations. When the event is coming up, the admins may need to provide a roster for each time slot to the event organizers, who are often outside the organization. We have a button in the Power App visible only to the admins which triggers a flow. That flow creates an export of a set of the specific event’s signup data in an Excel spreadsheet and the admin is notified via an email with a link to the Excel file when it is complete.

Here’s the sequence that solved the issue for me:

  • Export the existing flow. The old flow was named CSRRosterExport1.
  • Import the exported flow’s ZIP file with a new name, but everything else exactly the same. The new flow’s name was ExportEventRoster.
  • In the Power App, add the newly instantiated flow as a connection. To do this, from the top menu, choose Action/ Power Automate and specify the Flow you’d like to call.
  • Replace all calls to the old flow with calls to the new flow. In this case, it was the onSelect events for two buttons, each of which passed slightly different parameters to the flow. It amounted to changing the CSRRosterExport1.Run() instances with ExportEventRoster.Run().

Now that I know the fix, it probably takes about 10 mins – at most. When our users see the error message, we can easily Band-Aid the problem. Of course, this issuE shouldn’t happen in the first place, so let’s hope Microsoft fixes it before we ever see the error again.

References

Testing Power Apps with Role-Based Security

When we build apps (or applications before them), we often build different behaviors or capabilities based on the role of the current user. For example, when I ask for some time off, my manager can approve it, but I can’t.

In a Power App, there are many different ways to implement role-based permissions. I’ve put a few articles into the Resources below showing some approaches.

See the source image

Testing the Power App by playing the different roles can be very hard. Each user who loads the Power App is themselves, right?

Well, here’s a trick I’ve been using to make things much easier for testing.

Here are the high level steps:

  • Set up the roles using whatever mechanisms you choose. As a SharePoint guy, I like to use lists wherever possible so it’s easy to maintain the roles over time.
  • In your Power App’s initial screen, set up logic to determine the current user and set variables to reflect that user’s role(s) at an app level. (You’re likely to have additional roles when you get deeper into the app, perhaps working with specific items. This approach works there, too!)
  • Add a Combo box to the screen which allows you to select any user.
  • Switch the current user to the “assumed user” when you want to test with that user and their role(s).

Determining the current user is easy: we just use the User() function. But the User() function isn’t really complete enough. I always then define a second variable for currentUser by getting their Office365Users.UserProfile. This requires the Office365Users connector.

When I create a new Power App, one of the first things I do is add these lines to the OnVisible property of the initial landing screen:

// User 
Set(thisUser, User());
Set(currentUser, Office365Users.UserProfile(thisUser.Email));

Between User() and Office365Users.UserProfile, this tells me most of the base information Microsoft 365 knows about the user. Yes, I could use Office365Users.MyProfile() to get the user’s profile information, but then this testing trick wouldn’t work. By using Office365Users.UserProfile and passing in an email address, I can get anyone’s user profile.

Add a Combo box to the screen and rename it to ComboBox_AssumePerson.

Set the Items for ComboBox_AssumePerson to:

Office365Users.SearchUser({searchTerm:ComboBox_AssumePerson.SearchText,top:10}) 

For the OnChange property, add code similar to the following. Here, I’m setting two variables to the selected user from ComboBox_AssumePerson: assumeUser and the currentUser we’ve already defined.

Set(assumeUser, ComboBox_AssumePerson.Selected);
Set(currentUser, ComboBox_AssumePerson.Selected);
Set(returnToLanding, true);
Navigate(PermissionCheck, ScreenTransition.Cover); 

Because of the way we’ve set up the Items for ComboBox_AssumePerson, on selection, we get an object which is equivalent to our call to Office365Users.UserProfile: same type of object, with the same properties.

Now change the last line in the // User code above to assume the selected user if there is one.

Set(currentUser, If(IsBlank(assumeUser), Office365Users.UserProfile(thisUser.Email), assumeUser));

Because I’m setting all the role information in the OnVisible property for the landing screen, just changing the currentUser isn’t enough. To make the change “stick”, I’m navigating to another screen called PermissionCheck which looks at the returnToLanding value in its OnVisible property, and if it it set to true, it navigates right back. That means the role-based calculations all happen again, but this time in the context of assumeUser.

If(returnToLanding, Set(returnToLanding, false); Back()); 

By the way, that PermissionCheck screen can be really handy, too. The only thing going on in that screen is to show the current user’s roles. I tend to set variables like isAdmin, isManager, isExecutive, or isContactTracer on the landing screen. The PermissionCheck screen shows me those values for the current or assumed user whenever I need to be sure what they are. It doesn’t need to be pretty, but by displaying your role-based variables, you have an easy way to check your logic.

Now you can wander around your Power App as the user you have selected and the permissions you have determined for that user.

How do we undo that user assumption? We simply clear the ComboBox_AssumePerson, which fires its OnChange property. Then this line from above sets things back to the real user who is using the Power App because assumeUser no longer has a value.

Set(currentUser, If(IsBlank(assumeUser), Office365Users.UserProfile(thisUser.Email), assumeUser));

Caveats

As with most things, there are some very clear caveats to this approach.

  • When you assume another user’s identity in the app, you’re still you beneath the covers. That means any items created in lists will still be created by you. You’re only able to assume the other user’s identity in the Power App itself.
  • Everywhere you figure out the user’s roles, be sure to use currentUser.Mail – NOT thisUser.Email – to match users from your permission structures. There’s an example of this in my previous post Power Apps: Filtering by Multi-select SharePoint Columns, where I check the user in Section 3.
  • Be sure you have some indication on your screens showing who you are while you’re running the Power App. I think this is a good practice, anyway, but it’s especially important when you have this capability set up. (Who am I again?) I usually have something like this in the upper right of every screen.
  • Some logic may not work with this approach. For example, I can display the User()‘s photo, but not the currentUser‘s.
  • For debugging – even after you launch the Power App for production use – you may want to leave this “back door” in place. But be sure to set the Visible property for ComboBox_AssumePerson so only someone in a role you consider an admin can use it. And make sure they understand it!

Resources

Power Apps: Filtering by Multi-select SharePoint Columns

No matter how long I work with the Power Platform, I’m always running into things which feel like they should be simple, but simply aren’t.

Recently, I needed to filter a SharePoint list as a data source which had a multi-select Person or Group column. It’s a simple idea, really. The list is one which I set up to contain a set of people within each department which play a particular role.

The list looks something like this:

You should get the idea. What I wanted to do was figure out if the current user shows up in any of the Business Segment Experts values for any department, and if so, give them specific rights to do certain things in the Power App. The hard part was the filtering.

If there are good articles out there about this, I couldn’t find them. (Videos just don’t work for me – maybe this is embedded in umpteen videos, but no Binglage found it if it is.) I finally figured it out, and so here’s yet another note to future me.

The solution is to use Ungroup either when first getting the information from the list or in subsequent steps.

I’ve put code similar to this in the onVisible event for the landing page for the Power App. This means it will run every time the user passes through the landing page. This should pick up any changes in the roles, which can be especially helpful in testing. I’ve numbered the sections in the code so I can explain it more easily below. (There’s no real formatter for PowerApps-ese, but surprisingly, JavaScript formatting works pretty well!)

// 1 - Department-based roles 
Refresh(Departments);
ClearCollect(DepartmentsCollection,Departments);
// 2 - Business Segment Expert
ClearCollect(BusinessSegmentExpertsCollection,Filter(Ungroup(ShowColumns(DepartmentsCollection, "ID", "Title", "BusinessSegmentExperts"),"BusinessSegmentExperts"), !IsBlank(Claims)));
// 3 - Find the user in the collection, if they are there
Set(thisBusinessSegmentExpert, First(Filter(BusinessSegmentExpertsCollection, Email = currentUser.Mail) ));
// 4 - Set a boolean indicating whether they are a BusinessSegmentExpert 
Set(isBusinessSegmentExpert, !IsBlank(thisBusinessSegmentExpert));
// 5 - Get info about the specific department for use in other filters, etc.
Set( 
     businessSegmentExpertDepartment,
     {
         Title: If(
             !IsBlank(thisBusinessSegmentExpert),
             thisBusinessSegmentExpert.Title,
             Blank()
         ),
         Id: If(
             !IsBlank(thisBusinessSegmentExpert),
             thisBusinessSegmentExpert.ID,
             Blank()
         )
     }
 ); 

Section 1

There are other columns in the Departments list I need to work with, so I first pull all the items into a collection with ClearCollect. The list isn’t ever going to have more than a few dozen items, but it’s more efficient to work with a collection than to continually go back to the list if you don’t need to.

Section 2

In this section, I’m pulling only the columns I need for this specific task into a collection, and I’m using the Ungroup function to transform the data to make it useful.

Let’s step through the piece parts.

First, I pull out only the columns I need:

ShowColumns(DepartmentsCollection, "ID", "Title", "BusinessSegmentExperts")

This gives me a table with just the columns ID, Title, and BusinessSegmentExperts. It makes the table I’m working with much less cluttered, thus easier to look at to understand it.

Next, I take the results of that and Ungroup the BusinessSegmentExperts.

Ungroup(...result from above...),"BusinessSegmentExperts")

That’s the magic bit. That transforms the info from a table of people to a set of rows of people. If I’m the only person in the multi-select column, it goes from this:

to this:

The ID and Title columns are off to the right – right in line with the people, and repeating for each person!

In essence, we go from this:

to this:

Section 3

The order of the columns above doesn’t really matter, and I can now filter by the user’s Email. Here I’m setting a variable to the current user’s item in the list, if there is one. By using First, I’m “flattening” the item from a table into a record. I know there should only be one entry per person (they can only play this role in one department); you obviously need to understand your data.

Set(thisBusinessSegmentExpert,First(Filter(BusinessSegmentExpertsCollection, Email = User().Email) ));

Section 4

In this line, I’m setting a boolean to indicate if the current user is a Business Segment Expert.

Set(isBusinessSegmentExpert, !IsBlank(thisBusinessSegmentExpert));

Once the isBusinessSegmentExpert boolean is set, I can use it to determine visibility of buttons, let it determine filters for other collections, etc.

Section 5

Finally, in Section 5, I’m grabbing the department for which the current user plays this role, if any. For sake of debugging, I’ve grabbed both the Title and the ID separately and set a variable with those values. It’s useful to be able to display the Title for readability, of course, but since I use the use the department as a lookup column, I use the `ID` for filtering.

Set( 
     businessSegmentExpertDepartment,
     {
         Title: If(
             !IsBlank(thisBusinessSegmentExpert),
             thisBusinessSegmentExpert.Title,
             Blank()
         ),
         Id: If(
             !IsBlank(thisBusinessSegmentExpert),
             thisBusinessSegmentExpert.ID,
             Blank()
         )
     }
 );

Elsewhere in the app, I can now use businessSegmentExpertDepartment.Title or businessSegmentExpertDepartment.Id anytime I need them.


There are a lot of pieces to all this, but the key learning from this for me was the power of Ungroup.

An unfortunate thing is the way you go about doing this in Power Apps is fundamentally different than how you go about doing it in Power Automate (flow). This is one of the reasons it’s tough for me to think about these different apps as part of a power “platform”. They are just so different.

❌
❌