I am trying to automatically enable pages for profiles (profileApexPageAccess doc) via Metadata API. Here is my method:

public static void updateProfileAccesses(String profileName, List<String> pageNames) {

    if(!String.isBlank(profileName)) {
        MetadataService.IMetadataPort service = createService();
        MetadataService.IReadResult readResult =        
                service.readMetadata('Profile', new String[] { profileName });
        MetadataService.Metadata[] records = readResult.getRecords();

       MetadataService.Profile p = (MetadataService.Profile)records[0];

       for(String pageName : pageNames) {

            Boolean isPageEnabled = false;

            for(MetadataService.ProfileApexPageAccess pa : p.pageAccesses) {
                if(pa.apexPage == pageName) {
                    pa.enabled = true;
                    isPageEnabled = true;
            if(!isPageEnabled) {
                System.debug('page is NOT in the list'); // this message never appears in the logs
                MetadataService.ProfileApexPageAccess pap = new MetadataService.ProfileApexPageAccess();
                pap.apexPage = pageName;
                pap.enabled = true;

       MetadataService.SaveResult[] sr = service.updateMetadata(new MetadataService.Metadata[] {p});
       if(sr!=null) {
            System.debug('sr error ' + sr[0].errors);

SaveResult always has an error with the following details:


You can't edit tab settings for AddOnDefinition, as it's not a valid tab.

I haven't found any info on AddOnDefinition and what it has to do with ProfileApexPageAccess. Does anyone know what that might mean?

UPD I've tried the same code in another dev org and got

You can't edit tab settings for Calibration, as it's not a valid tab.


AND I found AddOnDefinition in ProfileTabVisibility list (tabVisibilities doc) but I still don't know how to get pass this error because I am not changing tabVisibilities at all.

Has anyone successfully updated page accesses automatically via Apex?

1 Answer 1


The profile that you are retrieving and then updating has many fields:

public class Profile extends Metadata {
    public String type = 'Profile';
    public String fullName;
    public MetadataService.ProfileApplicationVisibility[] applicationVisibilities;
    public MetadataService.ProfileApexClassAccess[] classAccesses;
    public Boolean custom;
    public MetadataService.ProfileCustomPermissions[] customPermissions;
    public String description;
    public MetadataService.ProfileExternalDataSourceAccess[] externalDataSourceAccesses;
    public MetadataService.ProfileFieldLevelSecurity[] fieldPermissions;
    public MetadataService.ProfileLayoutAssignment[] layoutAssignments;
    public MetadataService.ProfileLoginHours loginHours;
    public MetadataService.ProfileLoginIpRange[] loginIpRanges;
    public MetadataService.ProfileObjectPermissions[] objectPermissions;
    public MetadataService.ProfileApexPageAccess[] pageAccesses;
    public MetadataService.ProfileRecordTypeVisibility[] recordTypeVisibilities;
    public MetadataService.ProfileTabVisibility[] tabVisibilities;
    public String userLicense;
    public MetadataService.ProfileUserPermission[] userPermissions;

and it sounds like the error is caused by something other than the pageAccesses data that you are trying to update. (Why tabs that don't exist or can't be updated get included when you query the profile is an open question.)

I suggest you try and work around the problem by clearing some of the other fields than pageAccesses starting with the one that includes "tab" in its name:

MetadataService.Profile p = (MetadataService.Profile)records[0];
p.tabVisibilities = new MetadataService.ProfileTabVisibility[] {};

and see if that eliminates the error.

Or instead of querying, you could "new" the Profile and just set its fullName and pageAccesses fields.

  • Hi Keith! Thanks HEAPS for your answer. Both of your suggestions do work without resetting tab visibilities. Do you know why they are not being reset? (i.e. can I expect that production users tab visibilities won't be spoiled this way?)
    – user39399
    Aug 20, 2015 at 10:29
  • 1
    @bananka In my experience metadata operations don't remove things by default. I can't absolutely guarantee that everything will be fine in production but if it works in a sandbox or a dev org it should work the same in production.
    – Keith C
    Aug 20, 2015 at 11:11
  • @KeithC It works! Thanks mate.
    – JPG
    Aug 13, 2020 at 18:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .