Fix Publishing Pages Page Layout URL

Posted on Posted in SharePoint 2007, STSADM Commands

This command was created to fix an issue with our upgraded sites as well as issues I discovered with sites that had been imported to new farms. What happened was that after the upgrade (or an import) the Page Layout URL (page.ListItem[FieldId.PageLayout]) for various publishing pages was pointing to the wrong place. This didn’t prevent the page from loading as the Layout property of the page was referencing the correct PageLayout object – what failed was the editing of the page settings (so edit a page and click Page->Page Settings).

When I attempted to edit the page settings I’d get an error due to this url being incorrect (pointed to the old location). So rather than create something one off I figured I’d make this a command that I could use later as I know I’ll need it any time I decide to move a site to a new site collection or farm. The command I created, gl-fixpublishingpagespagelayouturl, is detailed below (apologies for the verbose name).

The code is pretty simple – I’m just resetting the URL based on what I know it should be (I’m using the existing page layout filename and just fixing the host and site collection path). You can also pass in a known page layout url or a regular expression search and replace string to use. I suggest you test this in a virtual environment or at least by using the test parameter to see what will change before running on your entire intranet. The core code is shown below (I left out the details about how I’m looping through the sites – download the code if you’d like to see that):

   1: public static void FixPages(PublishingWeb publishingWeb, string pageName, string pageLayoutUrl, Regex searchRegex, string replaceString, bool verbose, bool fixContact, bool test)
   2: {
   3:     if (!PublishingWeb.IsPublishingWeb(publishingWeb.Web))
   4:         return;
   6:     PublishingPageCollection pages;
   7:     int tryCount = 0;
   8:     while (true)
   9:     {
  10:         try
  11:         {
  12:             tryCount++;
  13:             pages = publishingWeb.GetPublishingPages();
  14:             break;
  15:         }
  16:         catch (InvalidPublishingWebException)
  17:         {
  18:             // The following is meant to deal with a timing issue when using this method in conjuction with other commands.  When
  19:             // used independently this should be unnecessary.
  20:             if (tryCount > 4)
  21:                 throw;
  22:             Thread.Sleep(10000);
  23:             SPWeb web = publishingWeb.Web;
  24:             SPSite site = web.Site;
  25:             string url = site.MakeFullUrl(web.ServerRelativeUrl);
  26:             site.Close();
  27:             site.Dispose();
  28:             web.Close();
  29:             web.Dispose();
  30:             publishingWeb.Close();
  31:             site = new SPSite(url);
  32:             web = site.OpenWeb(Utilities.GetServerRelUrlFromFullUrl(url));
  33:             publishingWeb = PublishingWeb.GetPublishingWeb(web);
  34:         }
  35:     }
  37:     foreach (PublishingPage page in pages)
  38:     {
  39:         if (!(string.IsNullOrEmpty(pageName) || page.Name.ToLower() == pageName.ToLower()))
  40:             continue;
  42:         if (verbose)
  43:         {
  44:             Log(string.Format("Begin processing {0}.", page.Url));
  45:             Log(string.Format("Current layout set to {0}.", page.ListItem[FieldId.PageLayout]));
  46:         }
  48:         // Can't edit items that are checked out.
  49:         if (Utilities.IsCheckedOut(page.ListItem))
  50:         {
  51:             if (verbose)
  52:                 Log("Page is already checked out - skipping.");
  53:             continue;
  54:         }
  56:         SPFieldUrlValue url;
  57:         if (string.IsNullOrEmpty(pageLayoutUrl))
  58:         {
  59:             if (searchRegex == null)
  60:             {
  61:                 if (page.ListItem[FieldId.PageLayout] == null || string.IsNullOrEmpty(page.ListItem[FieldId.PageLayout].ToString().Trim()))
  62:                 {
  63:                     if (verbose)
  64:                         Log(string.Format("Current page layout is empty - skipping.  Use the 'pagelayout' parameter to set a page layout."));
  66:                     continue;
  67:                 }
  69:                 // We didn't get a layout url passed in or a regular expression so try and fix the existing url
  70:                 url = new SPFieldUrlValue(page.ListItem[FieldId.PageLayout].ToString());
  71:                 if (string.IsNullOrEmpty(url.Url) ||
  72:                     url.Url.IndexOf("/_catalogs/") < 0)
  73:                 {
  74:                     if (verbose)
  75:                         Log(string.Format("Current page layout does not point to a _catalogs folder or is empty - skipping.  Use the 'pagelayout' parameter to set a page layout  Layout Url: {0}",
  76:                                 url));
  77:                     continue;
  78:                 }
  81:                 string newUrl = publishingWeb.Web.Site.ServerRelativeUrl.TrimEnd('/') +
  82:                               url.Url.Substring(url.Url.IndexOf("/_catalogs/"));
  84:                 string newDesc = publishingWeb.Web.Site.MakeFullUrl(newUrl);
  86:                 if (url.Url.ToLowerInvariant() == newUrl.ToLowerInvariant())
  87:                 {
  88:                     if (verbose)
  89:                         Log("Current layout matches new evaluated layout - skipping.");
  90:                     continue;
  91:                 }
  92:                 url.Url = newUrl;
  93:                 url.Description = newDesc;
  94:             }
  95:             else
  96:             {
  97:                 if (page.ListItem[FieldId.PageLayout] == null || string.IsNullOrEmpty(page.ListItem[FieldId.PageLayout].ToString().Trim()))
  98:                     if (verbose)
  99:                         Log(string.Format("Current page layout is empty - skipping.  Use the pagelayout parameter to set a page layout."));
 101:                 // A regular expression was passed in so use it to fix the page layout url if we find a match.
 102:                 if (searchRegex.IsMatch((string)page.ListItem[FieldId.PageLayout]))
 103:                 {
 104:                     url = new SPFieldUrlValue(page.ListItem[FieldId.PageLayout].ToString());
 105:                     string newUrl = searchRegex.Replace((string)page.ListItem[FieldId.PageLayout], replaceString);
 106:                     if (url.ToString().ToLowerInvariant() == newUrl.ToLowerInvariant())
 107:                     {
 108:                         if (verbose)
 109:                             Log("Current layout matches new evaluated layout - skipping.");
 110:                         continue;
 111:                     }
 112:                     url = new SPFieldUrlValue(newUrl);
 113:                 }
 114:                 else
 115:                 {
 116:                     if (verbose)
 117:                         Log("Existing page layout url does not match provided regular expression - skipping.");
 118:                     continue;
 119:                 }
 120:             }
 121:         }
 122:         else
 123:         {
 124:             // The user passed in an url string so use it.
 125:             if (pageLayoutUrl.ToLowerInvariant() == (string)page.ListItem[FieldId.PageLayout])
 126:             {
 127:                 if (verbose)
 128:                     Log("Current layout matches provided layout - skipping.");
 129:                 continue;
 130:             }
 132:             url = new SPFieldUrlValue(pageLayoutUrl);
 133:         }
 135:         string fileName = url.Url.Substring(url.Url.LastIndexOf('/'));
 136:         // Make sure that the URLs are server relative instead of absolute.
 137:         if (url.Description.ToLowerInvariant().StartsWith("http"))
 138:             url.Description = Utilities.GetServerRelUrlFromFullUrl(url.Description) + fileName;
 139:         if (url.Url.ToLowerInvariant().StartsWith("http"))
 140:             url.Url = Utilities.GetServerRelUrlFromFullUrl(url.Url) + fileName;
 142:         if (page.ListItem[FieldId.PageLayout] != null && url.ToString().ToLowerInvariant() == page.ListItem[FieldId.PageLayout].ToString().ToLowerInvariant())
 143:             continue; // No difference detected so move on.
 145:         if (verbose)
 146:             Log(string.Format("Changing layout url from \"{0}\" to \"{1}\"", page.ListItem[FieldId.PageLayout], url));
 149:         if (fixContact)
 150:         {
 151:             SPUser contact = null;
 152:             try
 153:             {
 154:                 contact = page.Contact;
 155:             }
 156:             catch (SPException)
 157:             {
 158:             }
 159:             if (contact == null)
 160:             {
 161:                 if (verbose)
 162:                     Log(string.Format("Page contact ('{0}') does not exist - assigning current user as contact.", page.ListItem[FieldId.Contact]));
 163:                 page.Contact = publishingWeb.Web.CurrentUser;
 165:                 if (!test)
 166:                     page.ListItem.SystemUpdate();
 167:             }
 168:         }
 170:         if (test)
 171:             continue;
 173:         page.CheckOut();
 174:         page.ListItem[FieldId.PageLayout] = url;
 175:         page.ListItem.UpdateOverwriteVersion();
 176:         PublishItems.Settings settings = new PublishItems.Settings();
 177:         settings.Test = test;
 178:         settings.Quiet = !verbose;
 179:         settings.LogFile = null;
 181:         PublishItems.PublishListItem(page.ListItem, page.ListItem.ParentList, settings, "stsadm -o fixpublishingpagespagelayouturl");
 182:         //page.ListItem.File.CheckIn("Fixed URL to page layout.", SPCheckinType.MajorCheckIn);
 183:         //if (page.ListItem.ModerationInformation != null)
 184:         //    page.ListItem.File.Approve("Publishing changes to page layout.");
 185:     }
 186: }

The syntax of the command can be seen below:

C:\>stsadm -help gl-fixpublishingpagespagelayouturl

stsadm -o gl-fixpublishingpagespagelayouturl

Fixes the Page Layout URL property of publishing pages which can get messed up during an upgrade or from importing into a new farm.

        -url <url>
        -scope <WebApplication | Site | Web | Page>
        [-pagename <if scope is Page, the name of the page to update>]
        {[-pagelayout <url of page layout to retarget page(s) to (format: "url, desc")>] /
         [-regexsearchstring <search pattern to use for a regular expression replacement of the page layout url>]
         [-regexreplacestring <replace pattern to use for a regular expression replacement of the page layout url>]}

To fix all the pages on a given web application you would use the following syntax:

stsadm –o gl-fixpublishingpagespagelayouturl –url "http://intranet/" -scope webapplication

Update 2/17/2008: I’ve made quite a few changes to this command. Note that if you have a previous version the syntax of the command has changed a lot (content above has been updated). You can now pass in a single url parameter along with a scope parameter. Also – you can now pass in a test parameter to simulate what changes would occur. The verbose switch will tell you what it’s doing. If you know you want to set a specific page to you can pass in the pagename parameter. Similarly if you want to set a specific page layout url use the pagelayout parameter or you can use the regex parameters for doing a search and replace. Note that if you pass in the pagelayout parameter you want to use the format "[url], [desc]" – for example:

stsadm -o gl-fixpublishingpagespagelayouturl -url "http://intranet" -scope site -pagelayout "http://intranet/_catalogs/masterpage/WelcomeLinks.aspx, /_catalogs/masterpage/WelcomeLinks.aspx".

134 thoughts on “Fix Publishing Pages Page Layout URL

  1. Hi Gary,

    I just want to let you know that you’ve saved our site!! We ran into the page layouts issue and after running this command our site is rid of that error.

    Thank you very much and keep up the good work!!

  2. Hi

    i’ve tried your command and i’ve this message:
    startIndex cannot be less than zero
    Parameter name: startIndex.

    What does it mean ?

  3. Manualito – I’ve updated this command quite a bit so you may want to pull down the latest and try again. If it still fails pass in the verbose parameter and send me the output and I’ll see if I can help you out.

  4. Hi Gary,

    Just to let you know this worked brilliantly in our environment and really saved my bacon!

    Just one thing, if a page doesn’t have an associated page layout, the process stops with a ‘object not set…’ error. Not a problem as associating a temporary page layout allows it to carry on, but just thought you should know

  5. I actually have a fix for that – I just haven’t had a chance to publish the latest build as I’ve got a ton of new stuff that I need to wrap up and stabilize first.

  6. Hey Gary… the posting was very helpful to me.

    I also found another solution from MS. If we open the publishing page in Sharepoint Designer and detach the master page check in and attach the master page back. Then open the page in the browser in Edit Mode and then going to Page->Page Settings and selecting a new page layout and publish the page is also fixing the problem.

    Just thought I would share… might be helpful to make a quick fix…

  7. Gary,

    Thanks a TON for this one. Looks like there is also a problem in Alternate Access Mappings when changing the public URL for a zone of a site. The page layouts retain their original URL, so I couldn’t create a new site with a default page using one of my layouts, or edit a page layout’s settings.

    Next Starera reunion, I owe you a beer!

    -Rich Finn

  8. Hi Gary,

    This looks like exactly what I need… I have manually updated the offending PageLayout in some pages to confirm that this is the problem.

    I have no idea how to get stsadm to use your custom commands. Do you have some doco on how its done.

    Many thanks!

  9. Hi Gary,

    Dont worry, found it. Just needed to stsadm -o deploysolution -local -allowgacdeployment -name “Lapointe.SharePoint.STSADM.Commands.wsp

  10. Hi,

    Thanks a million for all the great commands. I have a problem that was mentioned earlier about the page without a page layout. I’m using reghostfile after an upgrade and then this command which both are ‘successful’ however the page still has the error directing you to reconnect the layout. Is my command wrong, the -verbose does not output anything?

    stsadm -o gl-fixpublishingpagespagelayouturl -url “http://intranet” -scope page -pagename “http://intranet/News/Pages/default.aspx” -pagelayout “http://intranet/_catalogs/masterpage/DefaultLayout.aspx, /_catalogs/masterpage/DefaultLayout.aspx” -verbose


  11. First off – thanks for your wonderful solution – but I have a question.

    Can you explain to me the reason for the absolute links? They make no sense to my mind – why not ref /_catalogs/masterpage/BlankWebPartPage.aspx
    rather than

    It seems to me that would resolve the issue across the board.

    I have manually editing the files and made the relative and they appear to work fine. I tried having it be a relative link w/in the stsadm command, but it still put it as an absolute.

    Can you explain why this is?


  12. The link doesn’t need to be absolute – I honestly can’t remember if I had a reason for making it absolute but a server relative url will do just fine. I’ll try to change it if I have time.

  13. Thanks for getting back to me so quickly. A couple of things – I could not run off of the allitems.aspx, but I could using the -url switch (by removing the /pages/forms/allitems.aspx).

    However, that did not solve the issue. gl-fix…. prefixes the PageLayoutTemplate with the absolute path (ie even when I put in “/_catalogs…” in the cmd line it puts in “http://myserver/_catalogs…” in the file.

    I had tested it before my prev post and that was why I asked re the relative vs absolute links.

    Currently I am forced to manually download the file and edit them. The main reason being is that we have multiple access points (ie through our network and also remotely through FBA) and as such we need it to reference not the server name but the relative link.

    Any thoughts?


  14. Hi Gary,

    Thanks a bunch for your work and contribution. We discovered this issue just a few days before launch of the our client’s site and thanks to you we were able to cut save ourselves from stressful late nights.

    Thank you!

  15. Matt – regarding your comment about the links being absolute – I’ve just pushed a new build out which sets the URL to be relative instead. Let me know if you have any issues with it.

  16. One thing that I forgot to mention in my previous comment about the code using the relative url now – it actually doesn’t matter that I’m setting the URL to be relative – the API is “fixing” the URL on its own so that even though I set it to be relative it changes it back to absolute – there’s actually nothing I can do about this as its done via internal code. I only fixed my code in case Microsoft decides to change how the URL is handled internally with any upcoming updates.

  17. Hi Gary
    Thanks for these commands. Helped me out numerous times now.
    I moved a Site from one area to another (within the same site collection) and for some reason the page layout was not retained on the default pages. If I view in “content and structure” the page layout field is blank.
    Tried to run your command but I get the following results:

    Progress: Begin processing Pages/default.aspx.
    Progress: Current layout set to .
    Object reference not set to an instance of an object.

    Any chance you know what this is?

  18. To be honest I’m not sure what is causing the error – I skimmed through my code and didn’t see any obvious spots that would give a null reference exception. Are you able to step through the code or perhaps add a try/catch and output the stack trace? You may try adding the pagelayout parameter to set the layout explicitly.

  19. Thanks Gary. Its a strange one indeed.
    I did specify the -pagelayout parameter but still got an error unfortunately.
    I’m not sure why the pages lost their page layout when I moved the subsites around, but the only way I was able to fix them was to recreate each and every one.
    Unfortunately I’m not able to step into the code at this time. As soon as I find more info on it, I’ll post it here.
    Thanks for your prompt assistance!

  20. Hi Gary,

    your stsadm extensions is exactly what I was looking for!
    But I have a problem with using it.
    I ran Deploy.bat, then Update.bat.
    Then I copypasted your sample command with changed website name:
    stsadm –o gl-fixpublishingpagespagelayouturl –url “http://NewNameOfMySite/” -scope webapplication

    When I run this command it doesn’t work. Looks like syntax error. If I try
    stsadm -help gl-fixpublishingpagespagelayouturl
    I get the message window:
    “Windows SharePoint Services administration tool has encounted a problem and nneds to close”

    Could you please comment on this?
    Thank you in advance!

  21. It would appear that something failed during the install. It shouldn’t matter but you don’t need to run the upgrade.bat file. Try running the deploy.bat file again or try manually installing the wsp without using the bat file. If that fails then simple put the dll in the GAC and copy the xml file to the 12 hive’s config folder.

  22. Thank you for your responce, Gary!
    I’ve tried to rerun deploy.bat, manually run commands from this file, copied dll file to GAC and 3 xml files to bin and command derictories. Now I don’t have a message error with -help command, but command still don’t work. Though I recieve a list of your extensions by stsadm -help. Could it be because I use non english Sharepoint version? I can’t read error vessages in console – all symbols turns into “?”. Maybe there’s some calls to functions in your code which have another names in non english versions of SP?

  23. Hi Gary,

    I think there’s a bug on line 61. Isn’t a continue statement missing there?

    Thank you!

    – Ricardo

  24. I’m pretty new to this stuff and it seems to be a bit over my head. I downloaded and installed the source files. Now when I run
    stsadm –o gl-fixpublishingpagespagelayouturl –url “http://intranet/” -scope webapplication
    I get a command line error. I am trying to export a subsite and then import it into a new site collection, I then get a File not found error on the site collection after the import.

    Any help as to what I’m doing wrong would be great.


  25. Ricardo – yes, there is supposed to be a continue there – if you look at the code in the download it is there but for some reason there’s a few things missing from the code in my post – I’ll update the post with the latest version of the code – thanks for pointing out the discrepency.

  26. Can you provide what the specific command line error is? Do any of the other gl-* commands work for you? If not then the extensions are probably just not installed correctly – use the addsolution and deploysolution commands to install the .wsp. The File Not Found error occurs in several situations – if you run the gl-repairsitecollectionimportedfromsubsite command it will attempt to fix most of the known issues (typically it’s due to either the master page not existing or the page layout not existing – don’t worry about the name of the command – I created to address some specific issues in converting sub-sites to site collections but the fixes are relevant to most import scenarios).

  27. It just says Command Line Error. I have tried the deploysolution it deployed but the other command still didn’t work. Does it matter which server this is done on?

  28. As long as you’re running on one of your WFEs you should be okay. When you say theother command still didn’t work do you mean the built-in addsolution (which you have to run before deploysolution) or some of my other custom commands?

  29. I meant the stsadm –o gl-fixpublishingpagespagelayouturl –url “http://intranet/” -scope webapplication.

  30. Hi,

    This is the first time I’ve ever commented on your blog, but I’ve been following it closely for quite some time now. I would like to start off by thanking you for your excellent work with these commands, they have given me lots of ideas in my own work.

    I do have a question about this command though, as I’ve seen the page layout problem appear on quite a few of my Farms lately.

    Do we have any information regarding
    a) the source of the problem. Is it a known bug, has Microsoft published any information abou tit ?
    b) Is there anything we can do to PREVENT this from happening, instead of running scripts to fix the problems that occur afterwards.

    I realize that these questions aren’t easily answered, but maybe someone reading this blog can shed some light over this issue.

  31. Disturbed (nice name :)) – thanks for the feedback! – The source of the problem can be a variety of things but typically it’s due to content migration issues. MSFT released a content deployment rollup a few weeks ago which may resolve most if not all of the issues but I’ve not had a chance to do any testing of it. One of the core problems though is that even if you store the link as a relative link it converts it to an absolute link so if you’re moving the content to another web app it will typically break (it’s odd though because I’ve seen situations where it didn’t break when I expected it would so it’s almost like there is some processing going on to account for the issue but that processing is somehow flawed as it’s not addressing all scenarios and I can’t figure out what the deliniator is). As far as preventing the issue – don’t use MSFT content deployment stuff 🙂 (of course the rollup may change that). Oh, and my import*/export* commands all use the content deployment API with the exception of gl-exportlistitem2 and gl-addlistitem which are completely custom and do address the issue.

  32. Thanks for responding.

    We’ve had this happen to us on quite a few installations where we’ve moved content databases between farms. So I suppose it cannot be DIRECTLY related to the content deployment mechanisms.

    This problem also recently occurred on a farm which is patched beyond belief (:>) with all the rollups and hotfixes you can think of, so I actually doubt that MS has released a solution yet.

    Oh well, I guess I’d better try to get in touch with MS Support and see if they have any comments on this issue.

  33. Gary,

    I too am running into the issue of the command
    stsadm –o gl-fixpublishingpagespagelayouturl –url “https://URL/” -scope webapplication

    not running. merely indicates a command error…I have ran on both the WFE and the CA…neither appear to execute.

  34. Make sure that the help for the command is working. Also, make sure you are typing the command in and not pasting it (looks like the hyphens for the parameters are not the standard hyphen).

  35. Hi, and thank you for your great extensions !
    I have test it and we have this error :

    >”C:\Program Files\Common Files\Microsoft Shared\
    web server extensions\12\BIN\STSADM.EXE” -o gl-fixpublishingpagespagelayouturl –
    url “” -scope webapplication

    User cannot be found.

    I don’t understand what happen. We have tried a basic command and there is no problem. An idea ?

  36. Try passing in the verbose parameter so you can see where it’s failing. Also – try passing in the fixcontact parameter. Most likely it’s failing on the save because of an invalid contact.

  37. Hi Gary and thanks for the wonderful fix!

    One question: how can we rollback what you’re doing?

    You know, in case the layout is changed and somehow something goes wrong – is there any easy roll back?

  38. Sure – just make sure versioning is enabled on your library (it is by default for the Pages library) and then simply go back to a previous version. Another thing is to use the -test parameter to see what it will do before it does it.

  39. Hi Gary,

    I LOVE YOU!!

    This problem occurred on our development environment today and was causing us a great deal of stress. Thank goodness google directed me to this blog entry! I ran your extension and it completely and utterly fixed my problem.

    Thanks so much!!


  40. Hi Gary,

    Thank you very much for your great extensions.

    I have a problem using them. We have MOSS server, I run the deploy.bat without any problem.
    Then when I run
    stsadm -help gl-fixpublishingpagespagelayouturl

    command, I get the help of your command properly but still, I cannot run the following command:

    stsadm –o gl-fixpublishingpagespagelayouturl –url “http://MySite/” -scope webapplication

    It seems it doesn’t know this command and brings the general help of stsadm.

    Do you have any idea?

    Thank you very much.

  41. Gary thank you for your reply. I don’t have any special character there, it’s minus. Do you have any other idea?

  42. Sorry – not a clue – if you manually retyped the whole command and it’s still giving you the error then I’m at a loss – especially if the help is working. The only time I’ve ever seen this happen is when someone had a special character in the command string.

  43. Gary, I retyped the command and it works now. It was really stupid, sorry 😀

    Now, I have other problems and questions:

    1) In one of applications I get this error:

    “The site is not valid. The ‘Pages’ document library is missing. “

    The publishing feature is activated in the application.

    2) After running the extension in other applications, when I try to edit the settings of involved pages, I get this error:

    User cannot be found. at Microsoft.SharePoint.SPUserCollection.GetByID(Int32 id)

    3) I have noticed this problem too late. We have some applications on 3 servers: test server, pre-production server and production server.
    Some months ago, we deployed from test to pre-production and from pre-production to production and now we perform just partial deployments.

    If I correct this problem in test server using the extension and then perform a partial deployment to second and third servers, the changes would be deployed or should I run your extension in every server?

    4) If I delete “http://oldserver” expression in all fields in all tables of content database, does it have the same effect as this extension? I ask this, because it may solve “user not found” problem as well.

    Thank you again very much for your help.

  44. Melanie – here’s my best guesses to your questions (sorry I’m a little late with this – been busy):
    1. Not really sure what the deal is with this – sounds like someone deleted the pages library – if it’s there make sure that it wasn’t deleted and then manually recreated. You might also want to try reactivating the publishing feature.

    2. Try running the gl-fixpagecontact command – basically what’s happened is that the page is referencing a user ID that doesn’t exist – a common problem if the user was deleted from the site collection or the page was migrated from another site.

    3. If your target environments didn’t start out using the blank site template (or no site template) and you are using the content deployment then you will run into the same issues whenever you do a migration so you’ll need to rerun the commands in each environment – I see this all the time which is why I created these two commands.

    4. You definitely don’t want to edit the content database – you’ll lose support from Microsoft and could encounter any number of issues. The gl-fixpublishingpagespagelayouturl and gl-fixpagecontact commands in conjuction with the gl-replacefieldvalues, gl-replacewebpartcontent, and gl-replacenavigationurls (released but not yet documented) commands were built to address the many issues encountered when migrating from one environment to another, without the need to edit the database thus maintaining your support with Microsoft.

  45. First of all congratulations on a fantastic set of extensions.

    I do have a quick question, in looking at the code it would seem that each change gets checked in as a major version regardless of whether the last version modified was a minor one or not – is this intentional? I guess i will need to make my own version, we have lots of in progress pages which we would not want to publish immediately but which do require the page layout url fixing…what would be great is if the last version was minor then it checked in as minor otherwise publish if you see what I mean.

  46. Hi Gary,

    I am getting error “Value does not fall within the expected range” after creating one page. I have checked there is no syntax error in the page.

    I have copied .aspx code using Microsoft Sharepoint Designer in same server page. I have edited page settings and tried to open that page but it gives error.

    Please help me to solve this.

  47. Hi Gary… I tried this tool, for a single layout page it destroyed the whole site (Other pages took the new fixed layout). Is this scenario logical, or did I misstype my command?

  48. Gary,

    This code is a great help, thank you for putting it up for all to use and learn from.

    I’m trying to determine if it is possible to fix older file versions in the event a user reverts to a previous version that uses the wrong PublishingPageLayout URL.

    Anyone know if there is any way to fix the PublishingPageLayout in the SPFileVersionCollection?

    So far I have not found a way to update version history short of completely recreating an article & history using correct values.

  49. I haven’t looked into modifying the version history but another option would be to use an event receiver and just adjust the layout as items are restored (so on every update check that the page layout is valid – not pretty but it would work).

  50. I was also having an issue “script error” and, as suggested by Gary, it was related to non standard hyphens. If you’re doing a copy/paste, delete and re-type the “-“s.

  51. Yeah – Auto Correct kept biting me in the a$$ with those hyphens – I finally got Live Writer configured to not do that so newer posts should be okay to copy and paste.

  52. Hi Gary,

    this is a very nice comman.

    After I applied (last night) it seems fixed the problems. However this morning I checked the sites again and the problem came back.

    More details on my case:

    I have two site collections in one web application; The non-root site collection is a backup of the root site collection. There are two sites are with publishing features enabled and not created with publishing templates.

    One of the two site is based on Search Center Template.

    Someone told me that Publishing feature has some timer jobs to sync the content. Probably those jobs change something back.

    However, I reran your command and it showed that these two sites are using the right pagelayout. The only thing is that the pages are using the absolute path. The command will change the absolute path to relatives.

    Any thoughts?


  53. Guangming – I’m not actually sure what’s going on. The only situation in which I know a timer job updates publishing pages is when Variations are involved. You might want to see if SP2 fixes this for you (there were some fixes related to the publishing page layout URL).

  54. I exported a subsite that uses the publisher template and when I imported I get page not found error of course. I am trying to run your command fixpublisghinpages but I do not understand how to work the command I just don’t have enough knowledge in this area. basically the site address is http://sharepointmain2:4000/bst and then I import that into http://sharepointmain2/bst into a new site collection but how should I setup the Paramaeters. I just have no clue at all everything I try does not work at all. If there is an example somewhere that would help I do better by example

  55. Is there a way to update the Page Layout URL so that resultant Url changes from this:
    “http://badrooturl/_catalogs/Masterpage/ContentTypeName.aspx, ContentTypeName”

    and looks like this:
    “/_catalogs/Masterpage/ContentTypeName.aspx, ContentTypeName”

    I like this better than the standard “/relativeURL, /relativeURL” format.

    I’ve tried using
    -regexsearchstring “http://badrooturl/”
    -regexreplacestring “/”

    Which seems to do the trick when using the -verbose -test. However when we arrive at a page without a PageLayout assigned the following error message displays and the processing terminates.

    Value cannot be null.
    Parameter name: input

    This error only occurs when I use the Regex pattern matching. Deleting the offending aspx pages running the utility and then restoring from the Recycle bin seems to do the trick.

    Full syntax below:
    stsadm -o gl-fixpublishingpagespagelayouturl -url “http://site” -scope site -verbose -test -regexsearchstring “http://badrooturl” -regexreplacestring “/”

  56. Every time I use stsadm to export and import a site between two site colelctions, the page layouts url is broken!

    Is that right? Can I fix that URL forever?


  57. Gary,

    thank you very much for this! Although my problem is not entirely solved.

    The page layout that goes wrong is connected to a custom publishing pages Content Type. Some custom columns are defined in this content type, which are then inherited (though the page layout) to the page.

    After migrating the pages to another site the page layout is broken (it contains the old url). Running your script updates the page layout to the correct url indeed, but erases all custom content type columns from the page. The publishing pages content type is present in the new site as well.

    Can you please advise?

    Thank you,

  58. Gary,

    following my previous post,

    I think that I figured out what happened. The Publishing Page Content Type was present with the same name in the destination site, but with a different guid. So, when pages were migrated to destination, Sharepoint could not link them with the same content type.

    I then proceeded to create a small console program to batch update the destination site pages with the correct content type.

    Your code about fixing the pages layout is – I believe – irrelevant to this particular happening.

    Thank you again,

  59. I found this site using [url=][/url] And i want to thank you for your work. You have done really very good site. Great work, great site! Thank you!

    Sorry for offtopic

  60. Everytime I try to use this command, I get an error of
    Value cannot be null.
    Parameter name:type

    I am entering the following:

    stsadm -o gl-fixpublishingpagespagelayouturl -url “http://server/depts/is” -scope site -pagelayout “http://server/depts/_catalogs/masterpage/WebPartPage.aspx,WebPartPage”

    I have tried every scope on multiple sites, and always receive the same error. What am I missing?

  61. Hi Gary,
    Thank you so much for developing this excellent tool. It got our sharepoint web site back in working order again. You are the dude!!


  62. Hi Gary,

    Love your work.

    When executing the following command I am recieving a “server out of memory error” and a “cannot complete this action” error.

    The server has 8gb ram and the stsadm process is only using about 2gb when running. So I don’t think it is actually a memory problem. I have executed the same command on others server and recieve the same errors. It also doesn’t error at the same aspx page in the pages list, so I don’t think it is an issue with aspx files. It doesn’t matter if I use the -verbose switch or not, the same error occurs.
    It does complete fine when I use the -test switch.
    Could it be a limitation with list size, there are 1210 aspx files to process in the pages list
    Any ideas?

    STSADM.EXE -o gl-fixpublishingpagespagelayouturl -url -scope web -regexsearchstring “http:\/\/\/site1\/_catalogs\/masterpage\/ArticleLayout\.aspx” -regexreplacestring “/_catalogs/masterpage/ArticleLayout.aspx” -verbose

    Thanks in advance !!

  63. Odd – I might not be disposing of something somewhere which would explain the leak (sure I checked everything but possible I missed something). Unfortunately I don’t have a 2007 dev environment at the moment so I can fix anything in that project right now – what I’d recommend you do is wrap the call to the command in a PowerShell script – it will run slower but it should avoid any leak issues.

  64. Thanks a lot Gary, been using this tool on my MOSS 2007 implementations, works like a charm!

    I would just like to point out that if a page is checked out, it’s page layout will not be fixed. In my case, I tried to fix the page layouts of the whole site collection and it so happened that I have a page checked out when i used your tool, all pages were fixed except for that one. I tried it again with the page now checked in, page fixed!

    Thanks again.

    Julius Serdone

  65. Hey
    Your could is suppose to save my work, because i need to fix the layout url. But i do not know how to deploy the code nor how to use it could you tell me how? i found a link but i did not understand how i am supposed to use it.
    Many Thanks

  66. Hi Gary,

    I am trying to use the gl-fixpublishingpagespagelayouturl command, but it does not seem to be doing anything. The Default.aspx page on our test server is linked to the Pagelayout on prod instead of dev. I must not be doing the syntax correctly, and I don’t see any examples for just changing a single page (all the other pages in the Pages directory are fine). Could you give me an example? It keeps telling me the operation completed successfully, but nothing happens!


  67. Hi Gary,

    I tried your command its saying operation completed successfully but its not doing anything.

    Can you tell me how can I fix only 1 hyperlink before running it to the entire web.

    when I check in SPdesigner I have
    test/mytest hyperlink as broken and mt.aspx as in page

    what should i write in -pagename?

    hypelink to be fixed or page in which this hyperlink reside.

    I am writing this command

    stsadm gl-fixpub -url”http://test” – pagename “hyperlink” or -pagename “page” -scope page

  68. Thanks for reply Gary,

    but how about hyperlink. in url I have to specify path of hyperlink?

    It is not taking whole path. So if I specify only server name how can I check for only 1 hyperlink?

    I am sorry I am new to this..

  69. Thanks for reply.

    I did what you said.

    It changing layout url and Operation completed successfully

    But when I go to SPdesigner and verify broken link its still broke. So its not fixing.

    Is there anything I am missing?

    Sorry if I am giving you hard time!!

  70. I am getting a command line error when I attempt to use this to update a web application. Here is the command I am using:

    stsadm -o gl-fixpublishingpagespagelayouturl –
    url -scope webapplication

    What am I doing wrong?

  71. Make sure you enter it all on one line (not sure if the line break after the “-” is just a result of how you entered in the comment or not). Also, make sure you’re not pasting in and that you are typing it out so as to avoid any unicode characters. I’m also assuming that the extensions are installed and that you can bring up the help for the extensions.

  72. Our problem is little different and these pagelayouts show state as None and not Customized/Ghosted.

    We got one utility code which tells you which pagelayout is Customized/Uncustomized/None

    And we have few pagelayouts which shows as None and these are the pagelayouts which are not getting updated by WSP solution and also we have content deployment jobs from dev to QA and I think the content deployment job is doing something with these pagelayouts.

    So how can we make state of these page layouts from None to UnCustomized?

    When we write code like


    it throws error like page layout is custom file and not part of site definition.

    Our wsp is only updating pagelayouts which have state Uncustomized

    Another amazing thing we found that

    there is a property of pagelayout SetupPath.

    When this is blank status is None and not Customized/Uncustomized.

    When it finds setup path it tries to find vti_hasdefaultcontent and then returns status as Customized/Uncustomized

    Right now few of our page layouts do have blank SetupPath and thats why status as None and wsp can not update those pagelayouts.

    We are now trying to set setuppath of those pagelayouts and but vti_setuppath is not getting updated…


    1. If you’ve deployed the pages via content deployment then you’ve effectively detached them from the feature and they are now stored in the content database; this is by design. You should not be editing the pages/layouts in the target site when using content deployment (they must be read-only).

  73. Hi Gary, I am getting the following error when I create a page using publishing page.Can you please help me.

    SharePoint Foundation Runtime Unexpected Microsoft.SharePoint.Publishing.InvalidPublishingWebException: The site is not valid. The ‘Pages’ document library is missing. at Microsoft.SharePoint.Publishing.PublishingWeb.GetPublishingListWithCleanup(PublishingListType list, Boolean throwExceptionOnInvalidWeb)


  74. I apologise for my ignorance, could you please tell how to use this command made for you? I don’t see any “download” link or something, you say the code is only if we wanted to see how it works, i’m a bit confused.
    Thank you in advance!


    1. Joel, on the top navigation bar there is a “downloads” link. From there find the WSP for your environment and follow the install instructions provided with it.

  75. Hi Gary,

    I am not an expert in sharepoint. I face the same layout issues after importing using stsadme.exe. But please explain how do I install your custome stsadm command and use it. I can’t find any link to download the solution. Please give me a brief description about deployment as well.


    1. On the top navigation bar there is a “downloads” link. From there find the WSP for your environment and follow the install instructions provided with it.

  76. Hi – Thanks for all the help on this site, but I still have a problem – I have a sitecollection that I upgraded from 2007 to 2010 fine but I cannot create page layouts – I get ‘Cannot open “PageLayoutTemplate.aspx”: no such file or folder.’ I have installed and run your suggested commands on a test copy of this site collection but I still get the same problem even though Repair-SPPageLayoutUrl completed successfully.

    Any ideas or suggestions would be welcome!



    1. Not sure if you (or anyone else is still having this problem). I received that same error message, and the way I resolved was copying the PageLayoutTemplate.aspx file from another site collection (where it existed in the _catalogs folder) to that site collection.

  77. I have recently attached the content DB to a new Farm and was having the issue.

    I run the command:
    stsadm –o gl-fixpublishingpagespagelayouturl –url “http://team.intranet/” -scope webapplication

    I’m using the setup account and running as administrator from the APP server but I’m getting the following error:
    Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

    I have checked SQL Server, and the account is a DBO for the required DB’s.

    1. Are you a site colleciton administrator though? Doesn’t matter if you’re farm admin or dbo on the database – you still need either a full control user policy for the web app or be a site collection admin (or at least contributor for the pages lib).

      1. I am doing it from the Central Admin Server with the Farm Admin Account.

        Does it need to be Site Collection Admin for all site collections? Is there a way I can bulk add this? there are over 300 site collections

  78. Hi,

    Thanks for these information. It helped a lot. But there is a problem that I need help. I’m trying to use your gl-fixpublishingpagespagelayouturl command but it gives an error.
    “This command is not valid for Sharepoint Foundation.”
    I’ve just installed the foundation commands but the error still exists.
    What can I do about it? Thanks.

    1. You need to install the Server cmdlets for this one to work as you don’t get publishing sites with foundation. So if you have foundation then this cmdlet is of no use to you – if you have server then uninstall the foundation cmdlets and install the server cmdlets.

  79. Hi Gary,

    Thanks for this excellent tool.
    Is there any way to determine page layout for the current site as at present it is pointing to old references.

      1. Hi Gary,

        Well, I did not have the pleasure of seeing this until after a migration to 2010 (as I really was not administering the 2007 environment.) Well, I have an issue that I am getting a correlation error if I go to edit page settings, and low and behold, the page layout is referencing a URL from long ago testing. Do you have any more specific guidance on how to go through an entire web application to remove a URL reference?

        1. If you download the 2010 cmdlets that I provide there’s an equivalent cmdlet to this 2007 command that will allow you to do a reset for an entire web application.

  80. Thanks for the reply.
    why it is mandatory to use allowgacdeployment command?
    Is there any way to use this wsp without deploying it to GAC?

    1. Because the assembly goes into the GAC – this is required or else stsadm/powershell will not see it – no way around that (which is why I make the source code available so you can see what it’s doing if necessary).

  81. I’m using the 2010 cmdlet and I keep getting the error :

    “Repair-SPPageLayoutUrl: A parameter cannot be found that matches name ‘url’. Category Info : Invalid Arguement: [Repair-SPPageLayoutUrl], ParameterBindingException. FullyWualifiedErrorId: NamedParameterNotFound, Lapointe.SharePointe2010.Automation.Cmdlets.Pages.SPCmdletRepairPageLayoutUrl”

    I’m using the same parameters that worked successfully for 2007 stsadm. Any idea what this error means?


      1. Thanks Gary! I can’t begin to tell you how much your commands helped during our migration and cleanup 🙂

  82. Hi Gary,

    I hope all is well…

    I know this is old stuff but I think this page layout update is exactly what I need. I am working with a customer, doing a MOSS -> MOSS migration; one hosting provider to another. The export/import process seems to be working as I need but I am having problems with a few sites page layouts; “This page is not using a valid page layout…”.

    You wouldn’t, by chance, still have this code hanging around would you?

    Thank you,
    Bob Mixon

  83. Gary, this doesn’t work on pages in subfolders within the pages library — any idea how to get to the subfolders?

  84. Hi Gary,
    I was reading your blog. I am facing this issue from two weeks. I want to implement your code.
    I am not able to see the download code link on your blog. Can you please provide me with instructions too as I am a beginner in Sharepoint?


  85. The code works fine for pages inside pages library but does not work if the pages reside inside folders in the pages library. How do I make it work for pages inside folders?

  86. I have installed “Sharepoint 2010 Standard, Internet Sites Trial” on Windows 8. When I try to run your cmdlet for Server, I get the error “This command is not valid for SharePoint Foundation.”. I dont understand how to correct this problem, can you please check?


  87. Is there anyone that can maybe help get this command working? I installed the .wsp but it acts like the command does not exist when I try to run it (Using wss 3.0). I know I am missing something simple. Any help would be awesome!


    1. Ryan, sorry for my delayed response – if you’re still having issues figuring it out let me know which WSP you downloaded and how you installed it and I’ll see if I can help you figure it out.

  88. Thanks for your cool command.

    Just let you and others know and help:

    when I run -url “http://url” -scope WebApplication I get command line error,

    But -scope WebApplication -url “http://url” works fine.

    the parameter sequence is important.

    hope to help others out.

Comments are closed.