Posted on:
Categories: SharePoint
Description:

Scenario

You migrate a SharePoint 2010 Site to SharePoint 2013 with SSRS 2012 SP1, while also converting the Site to Claims Based Authentication.
When you click on "Manage Data Sources" on a report the following error is displayed: "Report Server has encountered a SharePoint error. ---> Microsoft.ReportingServices.Diagnostics.Utilities.SharePointException: Report Server has encountered a SharePoint error. ---> Microsoft.SharePoint.SPException: User cannot be found."

    Solution

    Update - Alternatively, I was also able to resolve this issue by installing SQL 2012 SP1 CU9 on the SharePoint server hosting SSRS.

    1. ULS Logs showed the following stack trace:
      1. Throwing Microsoft.ReportingServices.Diagnostics.Utilities.SharePointException: , Microsoft.ReportingServices.Diagnostics.Utilities.SharePointException: Report Server has encountered a SharePoint error. ---> Microsoft.SharePoint.SPException: User cannot be found.
        at Microsoft.SharePoint.SPUserCollection.get_Item(String loginName)
        at Microsoft.ReportingServices.SharePoint.Objects.RSSPImpFile.get_Author()
        at Microsoft.ReportingServices.SharePoint.Server.SharePointServiceHelper.SyncToRSCatalog(ExternalItemPath path, Boolean createOnly) -
        -- End of inner exception stack trace ---;
    2. Let's have a look at the SSRS code to see where SSRS gets the Author from:
      1. Then the following code is ran which is what throws our expectation.
    3. The code takes the SPFile.Properties["vti_author"] and tries to resolve the user using SPWeb.SiteUsers Collection, which returns "User cannot be found."
    4. I compared the Properties["vti_author"] on a SSRS Report which was working. The difference was that the broken one did not have the claims prefix "i:0#.w|"
      1. It appears that the Claims Migration does not update this property, I have validated this on a number of farms.
    5. Next, I wrote a script to resolve this issue:
      1. As I was writing the script, I noticed that this issue also occurs on SPFile.Properties["vti_modifiedby"]. The script will resolve both issues.
      2. Throwing Microsoft.ReportingServices.Diagnostics.Utilities.SharePointException: , Microsoft.ReportingServices.Diagnostics.Utilities.SharePointException: Report Server has encountered a SharePoint error. ---> Microsoft.SharePoint.SPException: User cannot be found.
        at Microsoft.SharePoint.SPFile.GetModifiedByFallback(String modifiedBy)
        at Microsoft.SharePoint.SPFile.get_ModifiedBy()
        at Microsoft.ReportingServices.SharePoint.Objects.RSSPImpFile.get_ModifiedBy()
        at Microsoft.ReportingServices.SharePoint.Server.SharePointServiceHelper.SyncToRSCatalog(ExternalItemPath path, Boolean createOnly) -
        -- End of inner exception stack trace ---;
     6. #----------------------------------------------------------------------------- 
     # Name: Fix-ClaimsConversionProperties.ps1  
     # Description: This script will update the vti_author and vti_modifiedby with the claims prefix
     #                     
     # Usage: Run the function with the required parameters
     # By: Ivan Josipovic, Softlanding.ca  
     #----------------------------------------------------------------------------- 
     
     Function Fix-ClaimsConversionProperties($webUrl, $listTitle) {
      $web = Get-SPWeb $webUrl;
      $list = $web.lists[$listTitle];
      
      foreach ($item in $list.Items){
       if (!$item.Properties["vti_author"].StartsWith("i:0#.w") -or !$item.Properties["vti_modifiedby"].StartsWith("i:0#.w")) {
        $item.Name;
        
        $currentAuthor = $item.Properties["vti_author"];
        if (!$currentAuthor.StartsWith("i:0#.w")) {
         try {
          $userAuthor = $web.EnsureUser($currentAuthor);
          $item.Properties["vti_author"] = $userAuthor.UserLogin;
         } catch {
          Write-Host "$currentAuthor user was not found! They were replaced with System.";
          $item.Properties["vti_author"] = $web.EnsureUser("SHAREPOINT\system").UserLogin;
         }
        }
        
        $currentModifiedBy = $item.Properties["vti_modifiedby"];
        if (!$currentModifiedBy.StartsWith("i:0#.w")) {
         try {      
          $item.Properties["vti_modifiedby"] = $web.EnsureUser($currentModifiedBy).UserLogin;
         } catch {
          Write-Host "$currentModifiedBy user was not found! They were replaced with System.";
          $item.Properties["vti_modifiedby"] = $web.EnsureUser("SHAREPOINT\system").UserLogin;
         }
        }
        
        $item["Editor"] = $web.EnsureUser("SHAREPOINT\system");
        $item.SystemUpdate();
        $item.Properties["vti_author"]
        $item.Properties["vti_modifiedby"]
       }
      }
     }