Skip to main content

Build a Career Development Plan App in Power Apps — Part 11: Build a Setup Flow That Creates the SharePoint Lists

· 33 min read
Jagdish Kumawat
Founder @ Dewiride

The app needs two SharePoint lists with exact column names, and so far they exist only because Part 2 made them by hand. This part builds a Power Automate flow that creates both lists, their settings and all 16 columns on any site, and that can run again without changing anything.

This is Part 11 of a 14-part series.

  1. Part 1: Plan the App and Set Up the Demo Organization
  2. Part 2: Create the SharePoint Site and Lists
  3. Part 3: Create the Solution, Environment Variables and Canvas App
  4. Part 4: Build the Home Screen
  5. Part 5: Build the My Plan Screen
  6. Part 6: Build the Response Screen
  7. Part 7: Share the App and Build the My Team Screens
  8. Part 8: Build the Review Screen for Manager Approvals
  9. Part 9: Let Managers Manage Competencies
  10. Part 10: Test Every Role, Joiners and Leavers
  11. Part 11: Build a Setup Flow That Creates the SharePoint Lists (you are here)
  12. Part 12: Run the Solution Checker and Export the Solutions
  13. Part 13: Install the App in a New Environment
  14. Part 14: Recap, Production Checklist and Next Steps

Anyone who installs the app needs the same two lists on their own site. Microsoft's environment variables article says that for SharePoint lists, each column's display name and logical name must match between the original lists and the ones the app moves to, and it warns that lists recreated by hand may not match. So the lists come from a flow: Create Career Development Plan Lists, in a small solution of its own, Career Development Plan Setup. You run it once with a site's address, and it creates whatever is missing.

I built it live and tested it on a new, empty site. Five things went wrong on the way, from a flow that landed in two solutions to a second run that waited half an hour before failing. Each is shown where it happened, and each has its own fixes post.

Get the Source Code​

Get the complete source code of Career Development Plan for Power Apps on Dewiride Store →

Use it to skip ahead, or to compare your app with the finished one. Every list, screen and formula is still built step by step in this series, for free.

What You'll Build​

The flow's steps, in order:

  1. Manually trigger a flow, with a Site URL input
  2. List definitions (Compose): both lists and their columns, as JSON
  3. Check the site: stops the run if the address is wrong
  4. For each list (Apply to each):
    1. Find the list, then If the list is missing, with Create the list in its True branch
    2. Update the list settings
    3. Make Title optional, Hide Title in new forms, Hide Title in edit forms and Hide Title in display forms
    4. Find Title in the view, then If Title is in the view, with Remove Title from the view in its True branch
    5. For each column (Apply to each): Find the column, then If the column is missing, with Create the column in its True branch

Every SharePoint step is a Send an HTTP request to SharePoint action from the standard SharePoint connector. Compose, Apply to each and Condition are built-in actions. Nothing here needs a premium license: Microsoft 365 licenses include creating and running cloud flows with standard connectors (Power Automate seeded licenses).

Every step that creates or removes something checks first, so a second run finds everything in place and changes nothing.

Prerequisites​

Step 1: Create an Empty Test Site​

Test the flow on a site of its own, not on the app's site from Part 2. The flow creates and changes lists, and an empty site is exactly what a new installation starts from. Create a communication site with the Blank template (How to Create a SharePoint Communication Site):

SettingValue
Site nameCareer Development Plan Test
Site descriptionTest site for the Career Development Plan setup flow.
Site address/sites/CareerDevelopmentPlanTest
LanguageEnglish
Time zone(UTC) Coordinated Universal Time

The Set up your site form with Site name Career Development Plan Test, the description Test site for the Career Development Plan setup flow., the site address https://contoso.sharepoint.com/sites/CareerDevelopmentPlanTest marked available, the language English, and Create site

The new site came up in Pacific Time, as the guide warns, so I set it to UTC like the app's site. Its Site contents had only what SharePoint creates with every site:

Site contents of the new Career Development Plan Test site, listing only Documents, Form Templates, Site Assets, Style Library, Events and Site Pages

Step 2: Create the Solution, Connection Reference and Flow​

The solution​

The flow gets a solution of its own because it runs before the app is installed: the app's environment variables point at lists, and the lists have to exist first. In Power Apps, create a second solution with the publisher from Part 3 (How to Create a Solution and Publisher):

FieldValue
Display nameCareer Development Plan Setup
NameCareerDevelopmentPlanSetup
PublisherDewiride (Dewiride)
Version0.1.0.0
Set as your preferred solutionTicked
DescriptionCreates the SharePoint lists for the Career Development Plan app on any site. Run its flow once, before you install the app.

The New solution panel with Display name Career Development Plan Setup, Name CareerDevelopmentPlanSetup, Publisher Dewiride (Dewiride), Version 0.1.0.0, Set as your preferred solution unticked, and the description under More options

:::warning Tick Set as your preferred solution

The screenshot shows my mistake: I left it unticked. The app's solution was still my preferred one, so the flow I created next was added to both solutions. Fixed: A New Cloud Flow Shows Up in Two Solutions shows how I found it and moved the flow without deleting anything.

:::

The connection reference​

In the new solution, select New → More → Connection Reference (How to Create a Connection Reference in a Solution):

FieldValue
Display nameCareer Development Plan Setup SharePoint
Namedewiride_CareerDevelopmentPlanSetupSharePoint
DescriptionSharePoint connection for the flow that creates the Career Development Plan lists.
ConnectorSharePoint
ConnectionYour SharePoint connection from Part 3

Every SharePoint action in the flow connects through it, and whoever imports the solution picks their own connection for it.

The flow​

Create an instant flow in the same solution (How to Create an Instant Cloud Flow Inside a Solution), and give its trigger a text input (How to Add a Text Input):

SettingValue
Flow nameCreate Career Development Plan Lists
TriggerManually trigger a flow
Input typeText
Input nameSite URL
Input descriptionThe address of the SharePoint site, for example https://contoso.sharepoint.com/sites/CareerDevelopmentPlan

Created from the solution, the flow opened in the classic designer. I built the first two steps there, saved, and did the rest in the new designer, opened from My flows → Edit, as the guide explains.

Step 3: Describe the Lists in List Definitions​

Add a Compose action under the trigger and rename it List definitions (How to Use the Compose Action). It holds everything the flow creates, as JSON, and every later step reads from it, so the lists are described in one place.

The JSON is an array with one object per list:

PropertyWhat it holds
titleThe list's name
descriptionThe list's description
noCrawltrue to keep the list out of search results
columnsOne entry per column: name, its internal name, and schemaXml, its definition

A column's schemaXml is the XML SharePoint uses to define a column, its Field element. Here's JobTitle in RoleCompetencies:

The JobTitle column's schemaXml
<Field Type='Text' Name='JobTitle' StaticName='JobTitle' DisplayName='JobTitle' Description='The job title this competency is for. Must match the job title in Microsoft 365 exactly.' Required='TRUE' MaxLength='255' Indexed='TRUE' />

Name and StaticName are the internal name, DisplayName is the name people see, and Indexed='TRUE' indexes the column, as Part 2 did for JobTitle and EmployeeId. How to Add a Column with CreateFieldAsXml explains each attribute, with an example of every column type the app uses.

I wrote the XML from Part 2's lists: I read their columns through SharePoint's REST API, and checked every description, choice, default and the column order against them before pasting. This is the complete value of Inputs:

List definitions → Inputs
[
{
"title": "RoleCompetencies",
"description": "Competencies and expected levels for each job title. Used by the Career Development Plan app.",
"noCrawl": false,
"columns": [
{
"name": "Competency",
"schemaXml": "<Field Type='Text' Name='Competency' StaticName='Competency' DisplayName='Competency' Description='The name of the competency, such as Customer skill or Leadership.' Required='TRUE' MaxLength='255' />"
},
{
"name": "JobTitle",
"schemaXml": "<Field Type='Text' Name='JobTitle' StaticName='JobTitle' DisplayName='JobTitle' Description='The job title this competency is for. Must match the job title in Microsoft 365 exactly.' Required='TRUE' MaxLength='255' Indexed='TRUE' />"
},
{
"name": "Level",
"schemaXml": "<Field Type='Choice' Name='Level' StaticName='Level' DisplayName='Level' Description='The level a person in this job title is expected to reach.' Required='TRUE' Format='Dropdown' FillInChoice='FALSE'><CHOICES><CHOICE>Beginner</CHOICE><CHOICE>Intermediate</CHOICE><CHOICE>Advanced</CHOICE><CHOICE>Expert</CHOICE></CHOICES></Field>"
},
{
"name": "IsActive",
"schemaXml": "<Field Type='Boolean' Name='IsActive' StaticName='IsActive' DisplayName='IsActive' Description='Yes: part of the plan. No: removed from the plan (the row is kept for history).' Required='TRUE'><Default>1</Default></Field>"
}
]
},
{
"title": "CompetencyResponses",
"description": "Employees' responses to their competencies, and their managers' reviews. Used by the Career Development Plan app.",
"noCrawl": true,
"columns": [
{
"name": "Competency",
"schemaXml": "<Field Type='Text' Name='Competency' StaticName='Competency' DisplayName='Competency' Description='The competency name, copied from RoleCompetencies when the response is sent.' Required='TRUE' MaxLength='255' />"
},
{
"name": "EmployeeId",
"schemaXml": "<Field Type='Text' Name='EmployeeId' StaticName='EmployeeId' DisplayName='EmployeeId' Description='The employee&apos;s Microsoft Entra object ID. The app finds a person&apos;s responses with it.' Required='TRUE' MaxLength='255' Indexed='TRUE' />"
},
{
"name": "EmployeeName",
"schemaXml": "<Field Type='Text' Name='EmployeeName' StaticName='EmployeeName' DisplayName='EmployeeName' Description='The employee&apos;s display name when the response was sent.' Required='TRUE' MaxLength='255' />"
},
{
"name": "EmployeeEmail",
"schemaXml": "<Field Type='Text' Name='EmployeeEmail' StaticName='EmployeeEmail' DisplayName='EmployeeEmail' Description='The employee&apos;s email address when the response was sent.' Required='TRUE' MaxLength='255' />"
},
{
"name": "JobTitle",
"schemaXml": "<Field Type='Text' Name='JobTitle' StaticName='JobTitle' DisplayName='JobTitle' Description='The employee&apos;s job title when the response was sent.' Required='TRUE' MaxLength='255' />"
},
{
"name": "RoleCompetencyId",
"schemaXml": "<Field Type='Number' Name='RoleCompetencyId' StaticName='RoleCompetencyId' DisplayName='RoleCompetencyId' Description='The ID of the RoleCompetencies row this response is for.' Required='TRUE' Decimals='0' CommaSeparator='FALSE' />"
},
{
"name": "Level",
"schemaXml": "<Field Type='Text' Name='Level' StaticName='Level' DisplayName='Level' Description='The expected level when the response was sent.' Required='TRUE' MaxLength='255' />"
},
{
"name": "Response",
"schemaXml": "<Field Type='Note' Name='Response' StaticName='Response' DisplayName='Response' Description='What the employee has done to show this competency at this level.' Required='TRUE' RichText='FALSE' />"
},
{
"name": "Status",
"schemaXml": "<Field Type='Choice' Name='Status' StaticName='Status' DisplayName='Status' Description='Pending until the manager approves or declines the response.' Required='TRUE' Format='Dropdown' FillInChoice='FALSE'><CHOICES><CHOICE>Pending</CHOICE><CHOICE>Approved</CHOICE><CHOICE>Declined</CHOICE></CHOICES><Default>Pending</Default></Field>"
},
{
"name": "ManagerComment",
"schemaXml": "<Field Type='Note' Name='ManagerComment' StaticName='ManagerComment' DisplayName='ManagerComment' Description='The manager&apos;s comment. The app asks for one when a response is declined.' RichText='FALSE' />"
},
{
"name": "SubmittedOn",
"schemaXml": "<Field Type='DateTime' Name='SubmittedOn' StaticName='SubmittedOn' DisplayName='SubmittedOn' Description='When the employee last sent the response.' Required='TRUE' Format='DateTime' FriendlyDisplayFormat='Disabled' />"
},
{
"name": "ReviewedOn",
"schemaXml": "<Field Type='DateTime' Name='ReviewedOn' StaticName='ReviewedOn' DisplayName='ReviewedOn' Description='When the manager approved or declined the response.' Format='DateTime' FriendlyDisplayFormat='Disabled' />"
}
]
}
]

The List definitions Compose action's Inputs showing the JSON array, starting with the RoleCompetencies list's title, description, noCrawl false and its first columns with their schemaXml

Two details keep it valid JSON: the XML uses single quotes, because the JSON string around it uses double quotes, and an apostrophe inside a description is written &apos;, as in employee&apos;s.

Step 4: Check the Site​

Add Send an HTTP request to SharePoint under List definitions and name it Check the site (How to Use Send an HTTP Request to SharePoint). Its pane says Connected to Career Development Plan Setup SharePoint: the connection reference from Step 2.

FieldValue
Site AddressEnter custom value, then the trigger's Site URL
MethodGET
Uri_api/web?$select=Title
HeadersAccept: application/json;odata=nometadata

The Check the site pane with Site Address set to the Site URL token, Method GET, Uri _api/web?$select=Title, the Accept header set to application/json;odata=nometadata, an empty header row and an empty Body

If the address is wrong, this request fails and nothing after it runs. Every SharePoint step after it uses the same Site Address.

Right after I saved, this action's pane showed No additional information is needed for this step and Not connected., with an empty Code view. Nothing was lost, as Fixed: "No Additional Information Is Needed for This Step" and "Not Connected" explains.

Step 5: Loop Over the Lists​

Add Apply to each under Check the site, name it For each list, and set Select an output from previous steps to Outputs under List definitions (How to Loop Through an Array with Apply to Each):

The For each list pane with Select an output from previous steps set to the Outputs token, and the loop on the canvas under Check the site

Inside the loop, this expression is the current list's title (How to Use the items() Function):

The current list's title
items('For_each_list')?['title']

Expressions go into a field through the expression editor (How to Add an Expression). Its Add button often needed two or three tries, and it said This expression has a problem about expressions that were correct. Fixed: "This Expression Has a Problem" covers both, and the one time the message was right.

Steps 6 to 9 all go inside this loop, so they run once for RoleCompetencies and once for CompetencyResponses.

Step 6: Create Each List Only When It's Missing​

I built most of the flow's requests by copying one that was close and changing what differed (How to Copy and Paste an Action). Three steps go first in the loop.

Find the list asks SharePoint for a list with the current title (How to Check Whether a SharePoint List Exists). It's a GET with the Accept header:

Find the list → Uri
_api/web/lists?$filter=Title eq '@{items('For_each_list')?['title']}'&$select=Id

If the list is missing is a Condition (How to Add a Condition) that compares this expression with the expression true. empty() is true when SharePoint found no list (How to Check Whether an Array Is Empty):

If the list is missing → Expression
empty(body('Find_the_list')?['value'])

In its True branch, Create the list creates a custom list with that title (How to Create a SharePoint List with the REST API):

FieldValue
MethodPOST
Uri_api/web/lists
HeadersAccept: application/json;odata=nometadata
Content-Type: application/json;odata=verbose
Create the list → Body
{
"__metadata": { "type": "SP.List" },
"BaseTemplate": 100,
"Title": "@{items('For_each_list')?['title']}"
}

The Create the list pane with Method POST, Uri _api/web/lists, the Accept and Content-Type headers, and the Body with __metadata type SP.List, BaseTemplate 100 and Title set to the title token

The False branch stays empty: when the list exists, there's nothing to create.

Step 7: Apply the List Settings​

After the condition, still inside the loop, Update the list settings sets what Part 2 set by hand (How to Change SharePoint List Settings with the REST API). It runs for new and existing lists alike, and every run sets the same values again.

FieldValue
MethodPOST
Uri_api/web/lists/getbytitle('@{items('For_each_list')?['title']}')
HeadersAccept: application/json;odata=nometadata
Content-Type: application/json;odata=verbose
IF-MATCH: *
X-HTTP-Method: MERGE
Update the list settings → Body
{
"__metadata": { "type": "SP.List" },
"Description": "@{items('For_each_list')?['description']}",
"EnableAttachments": false,
"EnableVersioning": true,
"MajorVersionLimit": 50,
"OnQuickLaunch": true,
"NoCrawl": @{if(items('For_each_list')?['noCrawl'], 'true', 'false')}
}

That's the description, attachments off, version history with 50 versions, a link in the site's navigation, and CompetencyResponses kept out of search, as in Part 2 (How to Turn Off Attachments and Hide a SharePoint List from Search).

The Update the list settings pane with the MERGE headers and the Body, where NoCrawl is set by an if(...) expression token

My first version wrote NoCrawl as @{items('For_each_list')?['noCrawl']}. That sends False with a capital F, which isn't JSON, and the run failed with Invalid JSON. A token was not recognized in the JSON content. The if() expression writes it in lowercase (How to Use the if() Function). The whole story is in Fixed: "Invalid JSON. A Token Was Not Recognized in the JSON Content".

Step 8: Hide the Title Column​

Every list has a Title column, and a list created with the REST API starts with it required and as the only column in its view. The app uses its own Competency column, so these steps hide Title, as Part 2 did (How to Hide the Title Column with the REST API). Every Uri starts with the current list:

The start of every Uri in this step
_api/web/lists/getbytitle('@{items('For_each_list')?['title']}')
ActionMethodThe Uri goes on with
Make Title optionalPOST/fields/getbyinternalnameortitle('Title')
Hide Title in new formsPOST/fields/getbyinternalnameortitle('Title')/setshowinnewform(false)
Hide Title in edit formsPOST/fields/getbyinternalnameortitle('Title')/setshowineditform(false)
Hide Title in display formsPOST/fields/getbyinternalnameortitle('Title')/setshowindisplayform(false)
Find Title in the viewGET/defaultview/viewfields
Remove Title from the viewPOST/defaultview/viewfields/removeviewfield('LinkTitle')

Make Title optional sends the same four headers as Update the list settings, with this body. The other five send only the Accept header, and no body.

Make Title optional → Body
{
"__metadata": { "type": "SP.Field" },
"Required": false
}

Remove Title from the view goes in the True branch of a Condition, If Title is in the view, which compares this expression with true (How to Check Whether an Array Contains a Value). In a view, Title is called LinkTitle:

If Title is in the view → Expression
contains(body('Find_Title_in_the_view')?['Items'], 'LinkTitle')

The flow with Hide Title in display forms, then Find Title in the view, then If Title is in the view with Remove Title from the view in its True branch and nothing in False, then For each column

The check wasn't in my first version. Removing a column that isn't in the view fails, and I found that out on the second run, in Step 11.

Step 9: Add the Columns​

The last step in For each list is a loop of its own, over the current list's columns. Add Apply to each, name it For each column, and give it this expression (Nest a Loop):

For each column → Select an output from previous steps
items('For_each_list')?['columns']

Inside it, the same check comes before the create. Find the column is a GET with the Accept header:

Find the column → Uri
_api/web/lists/getbytitle('@{items('For_each_list')?['title']}')/fields?$filter=InternalName eq '@{items('For_each_column')?['name']}'&$select=InternalName

If the column is missing compares this with true:

If the column is missing → Expression
empty(body('Find_the_column')?['value'])

In its True branch, Create the column sends the column's XML to SharePoint (How to Add a Column with CreateFieldAsXml):

FieldValue
MethodPOST
Uri_api/web/lists/getbytitle('@{items('For_each_list')?['title']}')/fields/createfieldasxml
HeadersAccept: application/json;odata=nometadata
Content-Type: application/json;odata=verbose

A code window titled Create the column — Body, showing the JSON body with parameters, __metadata type SP.XmlSchemaFieldCreationInformation, SchemaXml set to the current column's schemaXml expression, and Options 25

Create the column → Body
{
"parameters": {
"__metadata": { "type": "SP.XmlSchemaFieldCreationInformation" },
"SchemaXml": "@{items('For_each_column')?['schemaXml']}",
"Options": 25
}
}

SchemaXml is the current column's XML from List definitions. Options adds up three values from Microsoft's AddFieldOptions: 1 puts the column in the forms, 8 makes the XML's Name its internal name, and 16 shows it in the default view (What Options 25 Means). The 8 is what keeps the internal names identical to Part 2's.

The Create the column pane with Method POST, the Uri ending in /fields/createfieldasxml with the title token, the Accept and Content-Type headers, and the Body with parameters, __metadata type SP.XmlSchemaFieldCreationInformation, SchemaXml set to the schemaXml token and Options 25

Save the flow. Every step is in place.

Step 10: Run It on the Empty Test Site​

Select Test, choose Manually, then Test, and Continue. Type the test site's address into Site URL, such as https://contoso.sharepoint.com/sites/CareerDevelopmentPlanTest with your own tenant's name, and select Run flow (How to Test a Cloud Flow Manually).

I tested after each group of steps rather than once at the end. These were the runs on the empty site:

RunWhat the flow had by thenResult
12:57 PMCheck the siteSucceeded: the site's title came back
1:23 PMThe list steps and Update the list settingsCreated RoleCompetencies, then failed on Update the list settings with Invalid JSON
1:28 PMThe if() fixSucceeded: both lists, with their settings
1:45 PMThe Title steps and For each columnSucceeded in 16 seconds: Title hidden and all 16 columns added

Afterwards, the test site's Site contents listed both lists, and both had a link in the site's navigation:

Site contents of the Career Development Plan Test site listing CompetencyResponses and RoleCompetencies as lists, with the two lists also in the site's navigation

RoleCompetencies showed its four columns, and no Title:

The test RoleCompetencies list with the columns Competency, JobTitle, Level and IsActive, and no Title

Its New item form asked for those four, each with its description, with IsActive already set to Yes:

The New item form of the test RoleCompetencies list with Competency, JobTitle, Level and IsActive, each with its description, and IsActive ticked Yes

Then I compared both lists with Part 2's through SharePoint's REST API. The list settings matched, and so did every column's internal name, type, required setting, length, index, choices, default and description. One thing differs under the hood: Part 2 hid Title through the list's content type, in SharePoint's settings pages, while the flow uses the column's own settings. The forms and views look the same.

Step 11: Run It Again​

A setup flow is only safe if a second run changes nothing. My first repeat run, at 1:48 PM, didn't finish in seconds. It showed Waiting for half an hour, then failed with Action 'Remove_Title_from_the_view' failed: BadGateway.

Inside the error was SharePoint's Invalid field name. The 1:45 PM run had already taken Title out of the view, so removing it again was an error. Power Automate retried that error twice, minutes apart, for each list, and Cancel didn't stop the run. A second attempt at 2:14 PM, before I knew the cause, failed the same way. Fixed: "Invalid Field Name" BadGateway When Removing a Column from a SharePoint View has the whole investigation.

The fix is the check in Step 8: Find Title in the view and If Title is in the view. With it, the next run on the same site took 8 seconds, and every Create step was skipped:

A repeat run with Find the list succeeded, If the list is missing succeeded, and Create the list in the True branch skipped

The finished run with Find Title in the view succeeded, If Title is in the view succeeded with Remove Title from the view skipped in its True branch, and For each column succeeded with Create the column skipped

To test the other branch, I put Title back into the test list's view with SharePoint's Show or hide columns and ran the flow again. It took 8 seconds, and Title was out of the view afterwards. The run history shows the whole day:

The run history with the 2:39 PM and 2:34 PM runs succeeded in 8 seconds, the 2:14 PM and 1:48 PM runs failed after 24 and 28 minutes, and the 1:45 PM run succeeded in 16 seconds

After the repeat runs, the lists still had exactly their 4 and 12 columns, with no duplicates.

The Problems I Hit​

ProblemWhereThe fixes post
The new flow was in two solutionsStep 2A New Cloud Flow Shows Up in Two Solutions
An action showed Not connected after savingStep 4"No Additional Information Is Needed for This Step"
A correct expression was flaggedSteps 5 to 9"This Expression Has a Problem"
Invalid JSON from the list settingsStep 7"Invalid JSON. A Token Was Not Recognized"
The second run waited half an hour, then failedStep 11"Invalid Field Name" BadGateway

Clean Up the Test Site​

The test site has done its job: Part 13 runs the flow on a new site in another environment. Keep it while you work through the series if you want to test changes to the flow, and delete it when you're done.

A SharePoint Administrator deletes a communication site from Active sites in the SharePoint admin center: select the site, then Delete (Delete a site). Microsoft keeps a deleted site for 93 days, so it can be restored in that time.

Common Mistakes​

MistakeWhat happensDo this instead
Creating the flow while another solution is preferredThe flow lands in both solutionsMake the Setup solution your preferred one first
Editing the flow from inside the solutionIt opens in the classic designer, with no New designer toggleOpen it from My flows → Edit
Testing on the app's own siteThe flow changes the lists the app usesTest on an empty site
Writing a true-or-false value as @{...}Invalid JSONUse if(value, 'true', 'false')
Removing Title from the view without checkingThe second run waits half an hour, then failsCheck Items for LinkTitle first
Leaving 8 out of OptionsColumns may get different internal namesUse 25

Troubleshooting​

SymptomLikely causeFix
Check the site failsSite URL is wrong, or the connection's account can't open the siteCopy the address from the site itself, and check that the account can open it
A loop shows Waiting for many minutesA step inside it is being retriedWait for the run to end, then read that step's Retry history
The flow is in two solutionsYour preferred solution was a different oneRemove it from the wrong solution with Remove from this solution
A column has an unexpected internal nameThe XML's Name wasn't usedCheck Options is 25

FAQ​

Can I run the flow on the site from Part 2?​

It's built for a new site, and I only ran it on the test site. Part 2's lists already exist, with Title hidden a different way, so there's nothing for the flow to create there, and I haven't tested what its settings steps would change on them.

Does it add any data?​

No. It creates the lists empty. Managers add their competencies in the app (Part 9).

How do I change a column later?​

Change its schemaXml in List definitions for new installations. The flow skips columns that already exist, so on an existing site, change the column in SharePoint as well.

Why does the flow check the site first?​

If Site URL is wrong, the run stops at the first request, before anything else is tried.

How long does it take?​

16 seconds for the first full run, and 8 seconds when everything already exists.

Conclusion​

The setup flow is finished and tested:

  • it lives in its own solution, Career Development Plan Setup, with a SharePoint connection reference;
  • one JSON value, List definitions, describes both lists and all 16 columns;
  • on an empty site it creates both lists, applies Part 2's settings, hides Title and adds every column, with the same internal names as Part 2's lists;
  • every step that creates or removes something checks first, so a second run takes 8 seconds and changes nothing.

Your preferred solution is now Career Development Plan Setup. Before you change the app again, make Career Development Plan your preferred solution (Change the Preferred Solution Later).

← Previous: Part 10: Test Every Role, Joiners and Leavers

Next → Part 12: Run the Solution Checker and Export the Solutions. Both solutions will be checked, given a release version and exported, ready to install anywhere.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.