Google Ads API is returning to beta status. Please read our blog post for more details.

Partial Failure

In the Google Ads API, you can request that valid operations be committed and failed ones return errors. This feature—called partial failure—allows you to handle the failed operations separately at the end. It is available in non-get methods of many Google Ads API services.

Technical details

To utilize this feature, you’ll need to set the partialFailure parameter of the method you'd like to use. This can be a bit different in each client library. For instance, do the following to turn on this feature when sending a request using mutateAdGroups:

Java

mutateAdGroups(String.valueOf(customerId), operations, true)

C#

MutateAdGroups(customerId.ToString(), operations, true, false)

Python

mutate_ad_groups(customer_id, operations, partial_failure=True)

PHP

mutateAdGroups($customerId, $operations, ['partialFailure' => true])

Ruby

mutate_ad_groups(customer_id, operations, partial_failure: true)

The service will carry out the operations that had no errors. It will return results for successful operations and errors for failed ones.

Usage

Assume that you need to add a set of ad groups to your account. However, some of the ad groups may have some issues. You want to create the valid ad groups, but have the failed ad groups returned along with their errors.

Create the operations and make the API call

Create the mutate operations and make the API call as usual.

Java

private MutateAdGroupsResponse createAdGroups(
    GoogleAdsClient googleAdsClient, long customerId, long campaignId) {
  // This AdGroup should be created successfully - assuming the campaign in the params exists.
  AdGroup group1 =
      AdGroup.newBuilder()
          .setCampaign(StringValue.of(ResourceNames.campaign(customerId, campaignId)))
          .setName(StringValue.of("Valid AdGroup: " + System.currentTimeMillis()))
          .build();
  // This AdGroup will always fail - campaign ID 0 in resource names is never valid.
  AdGroup group2 =
      AdGroup.newBuilder()
          .setCampaign(StringValue.of(ResourceNames.campaign(customerId, 0L)))
          .setName(StringValue.of("Broken AdGroup: " + System.currentTimeMillis()))
          .build();
  // This AdGroup will always fail - duplicate ad group names are not allowed.
  AdGroup group3 =
      AdGroup.newBuilder()
          .setCampaign(StringValue.of(ResourceNames.campaign(customerId, campaignId)))
          .setName(group1.getName())
          .build();

  AdGroupOperation op1 = AdGroupOperation.newBuilder().setCreate(group1).build();
  AdGroupOperation op2 = AdGroupOperation.newBuilder().setCreate(group2).build();
  AdGroupOperation op3 = AdGroupOperation.newBuilder().setCreate(group3).build();

  try (AdGroupServiceClient service =
      googleAdsClient.getLatestVersion().createAdGroupServiceClient()) {
    // Issues the mutate request, setting partialFailure=true.
    return service.mutateAdGroups(
        String.valueOf(customerId),
        Arrays.asList(op1, op2, op3),
        // Sets partial failure to true.
        true,
        // Sets validate only to false.
        false);
  }
}

C#

private static MutateAdGroupsResponse CreateAdGroups(GoogleAdsClient client,
    long customerId, long campaignId)
{
    // Get the AdGroupServiceClient.
    AdGroupServiceClient adGroupService = client.GetService(Services.V2.AdGroupService);

    string validAdGroupName = "Valid AdGroup: " + ExampleUtilities.GetRandomString();

    AdGroupOperation[] operations = new AdGroupOperation[]
    {
        // This operation will be successful, assuming the campaign specified in
        // campaignId parameter is correct.
        new AdGroupOperation()
        {
            Create = new AdGroup()
            {
                Campaign = ResourceNames.Campaign(customerId, campaignId),
                Name = validAdGroupName
            }
        },
        // This operation will fail since we are using campaign ID = 0, which results
        // in an invalid resource name.
        new AdGroupOperation()
        {
            Create = new AdGroup()
            {
                Campaign = ResourceNames.Campaign(customerId, 0),
                Name = "Broken AdGroup: " + ExampleUtilities.GetRandomString()
            },
        },
        // This operation will fail since the ad group is using the same name as the ad
        // group from the first operation. Duplicate ad group names are not allowed.
        new AdGroupOperation()
        {
            Create = new AdGroup()
            {
                Campaign = ResourceNames.Campaign(customerId, campaignId),
                Name = validAdGroupName
            }
        }
    };

    // Add the ad groups.
    MutateAdGroupsResponse response =
        adGroupService.MutateAdGroups(customerId.ToString(), operations, true, false);
    return response;
}

Python

def create_ad_groups(client, customer_id, campaign_id):
    """Creates three Ad Groups, two of which intentionally generate errors.

    Args:
        client:  An initialized GoogleAdsClient instance.
        customer_id: A valid customer account ID.
        campaign_id: The ID for a campaign to create Ad Groups under.

    Returns: A MutateAdGroupsResponse message instance.
    """
    ad_group_service = client.get_service('AdGroupService', version='v2')
    campaign_service = client.get_service('CampaignService', version='v2')
    resource_name = campaign_service.campaign_path(customer_id, campaign_id)

    invalid_resource_name = campaign_service.campaign_path(customer_id, 0)
    ad_group_operations = []

    # This AdGroup should be created successfully - assuming the campaign in
    # the params exists.
    ad_group_op1 = client.get_type('AdGroupOperation', version='v2')
    ad_group_op1.create.name.value = 'Valid AdGroup: %s' % uuid.uuid4()
    ad_group_op1.create.campaign.value = resource_name
    ad_group_operations.append(ad_group_op1)

    # This AdGroup will always fail - campaign ID 0 in resource names is
    # never valid.
    ad_group_op2 = client.get_type('AdGroupOperation', version='v2')
    ad_group_op2.create.name.value = 'Broken AdGroup: %s' % (uuid.uuid4())
    ad_group_op2.create.campaign.value = invalid_resource_name
    ad_group_operations.append(ad_group_op2)

    # This AdGroup will always fail - duplicate ad group names are not allowed.
    ad_group_op3 = client.get_type('AdGroupOperation', version='v2')
    ad_group_op3.create.name.value = (ad_group_op1.create.name.value)
    ad_group_op3.create.campaign.value = resource_name
    ad_group_operations.append(ad_group_op3)

    # Issue a mutate request, setting partial_failure=True.
    return ad_group_service.mutate_ad_groups(customer_id, ad_group_operations,
                                             partial_failure=True)
    

PHP

private static function createAdGroups(
    GoogleAdsClient $googleAdsClient,
    int $customerId,
    int $campaignId
) {
    $campaignResourceName =
        new StringValue(['value' => ResourceNames::forCampaign($customerId, $campaignId)]);

    // This ad group should be created successfully - assuming the campaign in the params
    // exists.
    $adGroup1 = new AdGroup([
        'name' => new StringValue(['value' => 'Valid AdGroup #' . uniqid()]),
        'campaign' => $campaignResourceName
    ]);

    // This ad group will always fail - campaign ID 0 in the resource name is never valid.
    $adGroup2 = new AdGroup([
        'name' => new StringValue(['value' => 'Broken AdGroup #' . uniqid()]),
        'campaign' => ResourceNames::forCampaign($customerId, 0)
    ]);

    // This ad group will always fail - duplicate ad group names are not allowed.
    $adGroup3 = new AdGroup([
        'name' => $adGroup1->getName(),
        'campaign' => $campaignResourceName
    ]);

    $operations = [];

    $adGroupOperation1 = new AdGroupOperation();
    $adGroupOperation1->setCreate($adGroup1);
    $operations[] = $adGroupOperation1;

    $adGroupOperation2 = new AdGroupOperation();
    $adGroupOperation2->setCreate($adGroup2);
    $operations[] = $adGroupOperation2;

    $adGroupOperation3 = new AdGroupOperation();
    $adGroupOperation3->setCreate($adGroup3);
    $operations[] = $adGroupOperation3;

    // Issues the mutate request, enabling partial failure mode.
    $adGroupServiceClient = $googleAdsClient->getAdGroupServiceClient();
    return $adGroupServiceClient->mutateAdGroups(
        $customerId,
        $operations,
        ['partialFailure' => true]
    );
}

Check if the returned response contains a partial failure error

You can check if the returned response contains a partial failure error by checking if the response's partial failure error is not empty:

Java

private boolean checkIfPartialFailureErrorExists(MutateAdGroupsResponse response) {
  return response.hasPartialFailureError();
}

C#

private static bool CheckIfPartialFailureErrorExists(MutateAdGroupsResponse response)
{
    return response.PartialFailureError == null;
}

Python

def is_partial_failure_error_present(response):
    """Checks whether a response message has a partial failure error.

    In Python the partial_failure_error attr is always present on a response
    message and is represented by a google.rpc.Status message. So we can't
    simply check whether the field is present, we must check that the code is
    non-zero. Error codes are represented by the google.rpc.Code proto Enum:
    https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto

    Args:
        response:  A MutateAdGroupsResponse message instance.

    Returns: A boolean, whether or not the response message has a partial
        failure error.
    """
    partial_failure = getattr(response, 'partial_failure_error', None)
    code = getattr(partial_failure, 'code', None)
    return code != 0

PHP

private static function checkIfPartialFailureErrorExists(MutateAdGroupsResponse $response)
{
    if (!is_null($response->getPartialFailureError())) {
        printf("Partial failures occurred. Details will be shown below.%s", PHP_EOL);
    } else {
        printf(
            "All operations completed successfully. No partial failures to show.%s",
            PHP_EOL
        );
    }
}

Handle succeeded and failed operations

If the result corresponding to the submitted operation succeeds, its message will contain a resource name. In this case, you can just print the information or use it for other purposes you want.

However, if the result contains nothing, it means that the corresponding operation has failed. You can extract its errors' details by starting from partial_failure_error of the response:

  • The partial_failure_error field has a type of Status, which contains a list of details.
  • Each detail corresponds to each submitted operation. It represents an instance of GoogleAdsFailure.
  • GoogleAdsFailure contains a list of GoogleAdsError objects. Therefore, one submitted operation can contain many errors.
  • GoogleAdsError tells you the eror message, error code and all other relevant details.

All client libraries provide utility functions for extracting these error details for you, so you don't need to worry about doing the above steps from scratch. Check the code snippets below for examples:

Java

private void printResults(MutateAdGroupsResponse response) throws InvalidProtocolBufferException {
  int operationIndex = 0;
  for (MutateAdGroupResult result : response.getResultsList()) {
    if (ErrorUtils.getInstance().isPartialFailureResult(result)) {
      // May throw on this line. Most likely this means the wrong version of the ErrorUtils
      // class has been used.
      for (GoogleAdsError error :
          ErrorUtils.getInstance()
              .getGoogleAdsErrors(operationIndex, response.getPartialFailureError())) {
        System.out.printf("Operation %d failed with error: %s%n", operationIndex, error);
      }
    } else {
      System.out.printf("Operation %d succeeded.%n", operationIndex);
    }
    ++operationIndex;
  }
}

C#

private void PrintResults(MutateAdGroupsResponse response)
{
    // Finds the failed operations by looping through the results.
    int operationIndex = 0;
    foreach (MutateAdGroupResult result in response.Results)
    {
        // This represents the result of a failed operation.
        if (result.IsEmpty())
        {
            List<GoogleAdsError> errors =
                response.PartialFailure.GetErrorsByOperationIndex(operationIndex);
            foreach (GoogleAdsError error in errors)
            {
                Console.WriteLine($"Operation {operationIndex} failed with " +
                    $"error: {error}.");
            }
        }
        else
        {
            Console.WriteLine($"Operation {operationIndex} succeeded.",
                operationIndex);
        }
        operationIndex++;
    }
}

Python

def print_results(client, response):
    """Prints partial failure errors and success messages from a response.

    This function shows how to retrieve partial_failure errors from a response
    message (in the case of this example the message will be of type
    MutateAdGroupsResponse) and how to unpack those errors to GoogleAdsFailure
    instances. It also shows that a response with partial failures may still
    contain successful requests, and that those messages should be parsed
    separately. As an example, a GoogleAdsFailure object from this example will
    be structured similar to:

    error_code {
      range_error: TOO_LOW
    }
    message: "Too low."
    trigger {
      string_value: ""
    }
    location {
      field_path_elements {
        field_name: "operations"
        index {
          value: 1
        }
      }
      field_path_elements {
        field_name: "create"
      }
      field_path_elements {
        field_name: "campaign"
      }
    }

    Args:
        client: an initialized GoogleAdsClient.
        response: a MutateAdGroupsResponse instance.
    """
    # Check for existence of any partial failures in the response.
    if is_partial_failure_error_present(response):
        print('Partial failures occurred. Details will be shown below.\n')
        # Prints the details of the partial failure errors.
        partial_failure = getattr(response, 'partial_failure_error', None)
        # partial_failure_error.details is a repeated field and iterable
        error_details = getattr(partial_failure, 'details', [])

        for error_detail in error_details:
            # Retrieve an instance of the GoogleAdsFailure class from the client
            failure_message = client.get_type('GoogleAdsFailure', version='v2')
            # Parse the string into a GoogleAdsFailure message instance.
            failure_object = failure_message.FromString(error_detail.value)

            for error in failure_object.errors:
                # Construct and print a string that details which element in
                # the above ad_group_operations list failed (by index number)
                # as well as the error message and error code.
                print('A partial failure at index {} occurred.\n'
                      'Error message: {}\nError code: {}'.format(
                          error.location.field_path_elements[0].index.value,
                          error.message, error.error_code))
    else:
        print('All operations completed successfully. No partial failure '
              'to show.')

    # In the list of results, operations from the ad_group_operation list
    # that failed will be represented as empty messages. This loop detects
    # such empty messages and ignores them, while printing information about
    # successful operations.
    for message in response.results:
        # Empty messages will have a byte size of zero.
        if message.ByteSize() == 0:
            continue

        print('Created ad group with resource_name: {}.'.format(
            message.resource_name))
    

PHP

private static function printResults(MutateAdGroupsResponse $response)
{
    // Finds the failed operations by looping through the results.
    $operationIndex = 0;
    foreach ($response->getResults() as $result) {
        /** @var AdGroup $result */
        if (PartialFailures::isPartialFailure($result)) {
            $errors = GoogleAdsErrors::fromStatus(
                $operationIndex,
                $response->getPartialFailureError()
            );
            foreach ($errors as $error) {
                printf(
                    "Operation %d failed with error: %s%s",
                    $operationIndex,
                    $error->getMessage(),
                    PHP_EOL
                );
            }
        } else {
            printf(
                "Operation %d succeeded: ad group with resource name '%s'.%s",
                $operationIndex,
                $result->getResourceName(),
                PHP_EOL
            );
        }
        $operationIndex++;
    }
}

Code examples

The ErrorHandling folder of each client library contains the following code example that shows how to use this feature:

Skicka feedback om ...

Google Ads API Beta
Google Ads API Beta
Behöver du hjälp? Besök vår supportsida.