Handle Partial Failure
Stay organized with collections
Save and categorize content based on your preferences.
Java
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package
com.google.ads.googleads.examples.errorhandling
;
import static
com.google.ads.googleads.examples.utils.CodeSampleHelper.getPrintableDateTime
;
import
com.beust.jcommander.Parameter
;
import
com.google.ads.googleads.examples.utils.ArgumentNames
;
import
com.google.ads.googleads.examples.utils.CodeSampleParams
;
import
com.google.ads.googleads.lib.GoogleAdsClient
;
import
com.google.ads.googleads.v21.errors.GoogleAdsError
;
import
com.google.ads.googleads.v21.errors.GoogleAdsException
;
import
com.google.ads.googleads.v21.errors.GoogleAdsFailure
;
import
com.google.ads.googleads.v21.resources.AdGroup
;
import
com.google.ads.googleads.v21.services.AdGroupOperation
;
import
com.google.ads.googleads.v21.services.AdGroupServiceClient
;
import
com.google.ads.googleads.v21.services.MutateAdGroupResult
;
import
com.google.ads.googleads.v21.services.MutateAdGroupsRequest
;
import
com.google.ads.googleads.v21.services.MutateAdGroupsResponse
;
import
com.google.ads.googleads.v21.utils.ErrorUtils
;
import
com.google.ads.googleads.v21.utils.ResourceNames
;
import
java.io.FileNotFoundException
;
import
java.io.IOException
;
import
java.util.Arrays
;
/**
* Shows how to handle partial failures. There are several ways of detecting partial failures. This
* highlights the top main detection options: empty results and error instances.
*
* <p>Access to the detailed error (<code>GoogleAdsFailure</code>) for each error is via a Any
* proto. Deserializing these to retrieve the error details is may not be immediately obvious at
* first, this example shows how to convert Any into <code>GoogleAdsFailure</code>.
*
* <p>Additionally, this example shows how to produce an error message for a specific failed
* operation by looking up the failure details in the <code>GoogleAdsFailure</code> object.
*/
public
class
HandlePartialFailure
{
private
static
class
HandlePartialFailureParams
extends
CodeSampleParams
{
@Parameter
(
names
=
ArgumentNames
.
CUSTOMER_ID
,
required
=
true
)
private
Long
customerId
;
@Parameter
(
names
=
ArgumentNames
.
CAMPAIGN_ID
,
required
=
true
)
private
Long
campaignId
;
}
public
static
void
main
(
String
[]
args
)
{
HandlePartialFailureParams
params
=
new
HandlePartialFailureParams
();
if
(
!
params
.
parseArguments
(
args
))
{
// Either pass the required parameters for this example on the command line, or insert them
// into the code here. See the parameter class definition above for descriptions.
params
.
customerId
=
Long
.
parseLong
(
"INSERT_CUSTOMER_ID"
);
params
.
campaignId
=
Long
.
parseLong
(
"INSERT_CAMPAIGN_ID"
);
}
GoogleAdsClient
googleAdsClient
=
null
;
try
{
googleAdsClient
=
GoogleAdsClient
.
newBuilder
().
fromPropertiesFile
().
build
();
}
catch
(
FileNotFoundException
fnfe
)
{
System
.
err
.
printf
(
"Failed to load GoogleAdsClient configuration from file. Exception: %s%n"
,
fnfe
);
System
.
exit
(
1
);
}
catch
(
IOException
ioe
)
{
System
.
err
.
printf
(
"Failed to create GoogleAdsClient. Exception: %s%n"
,
ioe
);
System
.
exit
(
1
);
}
try
{
new
HandlePartialFailure
().
runExample
(
googleAdsClient
,
params
.
customerId
,
params
.
campaignId
);
}
catch
(
GoogleAdsException
gae
)
{
// GoogleAdsException is the base class for most exceptions thrown by an API request.
// Instances of this exception have a message and a GoogleAdsFailure that contains a
// collection of GoogleAdsErrors that indicate the underlying causes of the
// GoogleAdsException.
System
.
err
.
printf
(
"Request ID %s failed due to GoogleAdsException. Underlying errors:%n"
,
gae
.
getRequestId
());
int
i
=
0
;
for
(
GoogleAdsError
googleAdsError
:
gae
.
getGoogleAdsFailure
().
getErrorsList
())
{
System
.
err
.
printf
(
" Error %d: %s%n"
,
i
++
,
googleAdsError
);
}
System
.
exit
(
1
);
}
}
/** Runs the example. */
public
void
runExample
(
GoogleAdsClient
googleAdsClient
,
long
customerId
,
long
campaignId
)
{
MutateAdGroupsResponse
response
=
createAdGroups
(
googleAdsClient
,
customerId
,
campaignId
);
// Checks for existence of any partial failures in the response.
if
(
checkIfPartialFailureErrorExists
(
response
))
{
System
.
out
.
println
(
"Partial failures occurred."
);
}
else
{
System
.
out
.
println
(
"All operations completed successfully. No partial failures to show."
);
return
;
}
// Finds the failed operations by looping through the results.
printResults
(
response
);
}
/**
* Attempts to create 3 ad groups with partial failure enabled. One of the ad groups will succeed,
* while the other will fail.
*/
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
(
ResourceNames
.
campaign
(
customerId
,
campaignId
))
.
setName
(
"Valid AdGroup: "
+
getPrintableDateTime
())
.
build
();
// This AdGroup will always fail - campaign ID 0 in resource names is never valid.
AdGroup
group2
=
AdGroup
.
newBuilder
()
.
setCampaign
(
ResourceNames
.
campaign
(
customerId
,
0
L
))
.
setName
(
"Broken AdGroup: "
+
getPrintableDateTime
())
.
build
();
// This AdGroup will always fail - duplicate ad group names are not allowed.
AdGroup
group3
=
AdGroup
.
newBuilder
()
.
setCampaign
(
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
(
MutateAdGroupsRequest
.
newBuilder
()
.
setCustomerId
(
String
.
valueOf
(
customerId
))
.
setCustomerId
(
Long
.
toString
(
customerId
))
.
addAllOperations
(
Arrays
.
asList
(
op1
,
op2
,
op3
))
.
setPartialFailure
(
true
)
.
build
());
}
}
/** Inspects a response to check for presence of partial failure errors. */
private
boolean
checkIfPartialFailureErrorExists
(
MutateAdGroupsResponse
response
)
{
return
response
.
hasPartialFailureError
();
}
/** Displays the result from the mutate operation. */
private
void
printResults
(
MutateAdGroupsResponse
response
)
{
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.
GoogleAdsFailure
googleAdsFailure
=
ErrorUtils
.
getInstance
()
.
getGoogleAdsFailure
(
response
.
getPartialFailureError
());
for
(
GoogleAdsError
error
:
ErrorUtils
.
getInstance
()
.
getGoogleAdsErrors
(
operationIndex
,
googleAdsFailure
))
{
System
.
out
.
printf
(
"Operation %d failed with error: %s%n"
,
operationIndex
,
error
);
}
}
else
{
System
.
out
.
printf
(
"Operation %d succeeded.%n"
,
operationIndex
);
}
++
operationIndex
;
}
}
}
C#
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using
CommandLine
;
using
Google.Ads.Gax.Examples
;
using
Google.Ads.Gax.Lib
;
using
Google.Ads.GoogleAds.Lib
;
using
Google.Ads.GoogleAds.V21.Errors
;
using
Google.Ads.GoogleAds.V21.Resources
;
using
Google.Ads.GoogleAds.V21.Services
;
using
System
;
using
System.Collections.Generic
;
namespace
Google.Ads.GoogleAds.Examples.V21
{
/// <summary>
/// This code example demonstrates how to handle partial failures.
/// </summary>
public
class
HandlePartialFailure
:
ExampleBase
{
/// <summary>
/// Command line options for running the <see cref="HandlePartialFailure"/> example.
/// </summary>
public
class
Options
:
OptionsBase
{
/// <summary>
/// The customer ID for which the call is made.
/// </summary>
[Option("customerId", Required = true, HelpText =
"The customer ID for which the call is made.")]
public
long
CustomerId
{
get
;
set
;
}
/// <summary>
/// ID of the campaign to which ad groups are added.
/// </summary>
[Option("campaignId", Required = true, HelpText =
"ID of the campaign to which ad groups are added.")]
public
long
CampaignId
{
get
;
set
;
}
}
/// <summary>
/// Main method, to run this code example as a standalone application.
/// </summary>
/// <param name="args">The command line arguments.</param>
public
static
void
Main
(
string
[]
args
)
{
Options
options
=
ExampleUtilities
.
ParseCommandLine<Options>
(
args
);
HandlePartialFailure
codeExample
=
new
HandlePartialFailure
();
Console
.
WriteLine
(
codeExample
.
Description
);
codeExample
.
Run
(
new
GoogleAdsClient
(),
options
.
CustomerId
,
options
.
CampaignId
);
}
/// <summary>
/// Returns a description about the code example.
/// </summary>
public
override
string
Description
=
>
"This code example demonstrates how to handle partial failures."
;
/// <summary>
/// Runs the code example.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="campaignId">ID of the campaign to which ad groups are added.</param>
public
void
Run
(
GoogleAdsClient
client
,
long
customerId
,
long
campaignId
)
{
try
{
MutateAdGroupsResponse
response
=
CreateAdGroups
(
client
,
customerId
,
campaignId
);
// Checks for existence of any partial failures in the response.
if
(
CheckIfPartialFailureErrorExists
(
response
))
{
Console
.
WriteLine
(
"Partial failures occurred. Details will be shown below."
);
}
else
{
Console
.
WriteLine
(
"All operations completed successfully. No partial "
+
"failures to show."
);
return
;
}
// Finds the failed operations by looping through the results.
PrintResults
(
response
);
}
catch
(
GoogleAdsException
e
)
{
Console
.
WriteLine
(
"Failure:"
);
Console
.
WriteLine
(
$"Message: {e.Message}"
);
Console
.
WriteLine
(
$"Failure: {e.Failure}"
);
Console
.
WriteLine
(
$"Request ID: {e.RequestId}"
);
throw
;
}
}
/// <summary>
/// Displays the result from the mutate operation.
/// </summary>
/// <param name="response">The mutate response from the Google Ads API server..</param>
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
++
;
}
}
/// <summary>
/// Inspects a response to check for presence of partial failure errors.
/// </summary>
/// <param name="response">The response.</param>
/// <returns>True if there are partial failures, false otherwise.</returns>
private
static
bool
CheckIfPartialFailureErrorExists
(
MutateAdGroupsResponse
response
)
{
return
response
.
PartialFailureError
!=
null
;
}
/// <summary>
/// Attempts to create 3 ad groups with partial failure enabled. One of the ad groups
/// will succeed, while the other will fail.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="campaignId">ID of the campaign to which ad groups are added.</param>
/// <returns>The mutate response from the Google Ads server.</returns>
private
static
MutateAdGroupsResponse
CreateAdGroups
(
GoogleAdsClient
client
,
long
customerId
,
long
campaignId
)
{
// Get the AdGroupServiceClient.
AdGroupServiceClient
adGroupService
=
client
.
GetService
(
Services
.
V21
.
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
(
new
MutateAdGroupsRequest
()
{
CustomerId
=
customerId
.
ToString
(),
Operations
=
{
operations
},
PartialFailure
=
true
,
ValidateOnly
=
false
});
return
response
;
}
}
}
PHP
< ?php
/**
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Google\Ads\GoogleAds\Examples\ErrorHandling;
require __DIR__ . '/../../vendor/autoload.php';
use GetOpt\GetOpt;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser;
use Google\Ads\GoogleAds\Examples\Utils\Helper;
use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V21\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V21\GoogleAdsException;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Util\V21\GoogleAdsErrors;
use Google\Ads\GoogleAds\Util\V21\PartialFailures;
use Google\Ads\GoogleAds\Util\V21\ResourceNames;
use Google\Ads\GoogleAds\V21\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V21\Resources\AdGroup;
use Google\Ads\GoogleAds\V21\Services\AdGroupOperation;
use Google\Ads\GoogleAds\V21\Services\MutateAdGroupsRequest;
use Google\Ads\GoogleAds\V21\Services\MutateAdGroupsResponse;
use Google\ApiCore\ApiException;
/**
* Shows how to handle partial failures. There are several ways of detecting partial failures. This
* highlights the top main detection options: empty results and error instances.
*
* <p>Access to the detailed error (<code>GoogleAdsFailure</code>) for each error is via a Any
* proto. Deserializing these to retrieve the error details is may not be immediately obvious at
* first, this example shows how to convert Any into <code>GoogleAdsFailure</code>.
*
* <p>Additionally, this example shows how to produce an error message for a specific failed
* operation by looking up the failure details in the <code>GoogleAdsFailure</code> object.
*/
class HandlePartialFailure
{
private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
private const CAMPAIGN_ID = 'INSERT_CAMPAIGN_ID_HERE';
public static function main()
{
// Either pass the required parameters for this example on the command line, or insert them
// into the constants above.
$options = (new ArgumentParser())->parseCommandArguments([
ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT,
ArgumentNames::CAMPAIGN_ID => GetOpt::REQUIRED_ARGUMENT
]);
// Generate a refreshable OAuth2 credential for authentication.
$oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();
// Construct a Google Ads client configured from a properties file and the
// OAuth2 credentials above.
$googleAdsClient = (new GoogleAdsClientBuilder())
->fromFile()
->withOAuth2Credential($oAuth2Credential)
->build();
try {
self::runExample(
$googleAdsClient,
$options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID,
$options[ArgumentNames::CAMPAIGN_ID] ?: self::CAMPAIGN_ID
);
} catch (GoogleAdsException $googleAdsException) {
printf(
"Request with ID '%s' has failed.%sGoogle Ads failure details:%s",
$googleAdsException->getRequestId(),
PHP_EOL,
PHP_EOL
);
foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) {
/** @var GoogleAdsError $error */
printf(
"\t%s: %s%s",
$error->getErrorCode()->getErrorCode(),
$error->getMessage(),
PHP_EOL
);
}
exit(1);
} catch (ApiException $apiException) {
printf(
"ApiException was thrown with message '%s'.%s",
$apiException->getMessage(),
PHP_EOL
);
exit(1);
}
}
/**
* Runs the example.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the customer ID
* @param int $campaignId a campaign ID
*/
public static function runExample(
GoogleAdsClient $googleAdsClient,
int $customerId,
int $campaignId
) {
$response = self::createAdGroups($googleAdsClient, $customerId, $campaignId);
self::checkIfPartialFailureErrorExists($response);
self::printResults($response);
}
/**
* Create ad groups by enabling partial failure mode.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the customer ID
* @param int $campaignId a campaign ID
* @return MutateAdGroupsResponse
*/
private static function createAdGroups(
GoogleAdsClient $googleAdsClient,
int $customerId,
int $campaignId
) {
$campaignResourceName = ResourceNames::forCampaign($customerId, $campaignId);
// This ad group should be created successfully - assuming the campaign in the params
// exists.
$adGroup1 = new AdGroup([
'name' => 'Valid AdGroup #' . Helper::getPrintableDatetime(),
'campaign' => $campaignResourceName
]);
// This ad group will always fail - campaign ID 0 in the resource name is never valid.
$adGroup2 = new AdGroup([
'name' => 'Broken AdGroup #' . Helper::getPrintableDatetime(),
'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(
MutateAdGroupsRequest::build($customerId, $operations)->setPartialFailure(true)
);
}
/**
* Check if there exists partial failure error in the given mutate ad group response.
*
* @param MutateAdGroupsResponse $response the mutate ad group response
*/
private static function checkIfPartialFailureErrorExists(MutateAdGroupsResponse $response)
{
if ($response->hasPartialFailureError()) {
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
);
}
}
/**
* Print results of the given mutate ad group response. For those that are partial failure,
* print all their errors with corresponding operation indices. For those that succeeded, print
* the resource names of created ad groups.
*
* @param MutateAdGroupsResponse $response the mutate ad group response
*/
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++;
}
}
}
HandlePartialFailure::main();
Python
#!/usr/bin/env python
# Copyright 2018 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This shows how to handle responses that may include partial_failure errors."""
import
argparse
import
sys
import
uuid
from
typing
import
Any
,
List
from
google.ads.googleads.client
import
GoogleAdsClient
from
google.ads.googleads.errors
import
GoogleAdsException
from
google.ads.googleads.v21.services.services.ad_group_service
import
(
AdGroupServiceClient
,
)
from
google.ads.googleads.v21.services.services.campaign_service
import
(
CampaignServiceClient
,
)
from
google.ads.googleads.v21.services.types.ad_group_service
import
(
AdGroupOperation
,
MutateAdGroupsResponse
,
MutateAdGroupsRequest
,
)
def
main
(
client
:
GoogleAdsClient
,
customer_id
:
str
,
campaign_id
:
str
)
-
> None
:
"""Runs the example code, which demonstrates how to handle partial failures.
The example creates three Ad Groups, two of which intentionally fail in
order to generate a partial failure error. It also demonstrates how to
properly identify a partial error and how to log the error messages.
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.
"""
try
:
ad_group_response
:
MutateAdGroupsResponse
=
create_ad_groups
(
client
,
customer_id
,
campaign_id
)
except
GoogleAdsException
as
ex
:
print
(
f
'Request with ID "
{
ex
.
request_id
}
" failed with status '
f
'"
{
ex
.
error
.
code
()
.
name
}
" and includes the following errors:'
)
for
error
in
ex
.
failure
.
errors
:
print
(
f
'
\t
Error with message "
{
error
.
message
}
".'
)
if
error
.
location
:
for
field_path_element
in
error
.
location
.
field_path_elements
:
print
(
f
"
\t\t
On field:
{
field_path_element
.
field_name
}
"
)
sys
.
exit
(
1
)
else
:
print_results
(
client
,
ad_group_response
)
def
create_ad_groups
(
client
:
GoogleAdsClient
,
customer_id
:
str
,
campaign_id
:
str
)
-
> MutateAdGroupsResponse
:
"""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
:
AdGroupServiceClient
=
client
.
get_service
(
"AdGroupService"
)
campaign_service
:
CampaignServiceClient
=
client
.
get_service
(
"CampaignService"
)
resource_name
:
str
=
campaign_service
.
campaign_path
(
customer_id
,
campaign_id
)
invalid_resource_name
:
str
=
campaign_service
.
campaign_path
(
customer_id
,
0
)
ad_group_operations
:
List
[
AdGroupOperation
]
=
[]
# This AdGroup should be created successfully - assuming the campaign in
# the params exists.
ad_group_op1
:
AdGroupOperation
=
client
.
get_type
(
"AdGroupOperation"
)
ad_group_op1
.
create
.
name
=
f
"Valid AdGroup:
{
uuid
.
uuid4
()
}
"
ad_group_op1
.
create
.
campaign
=
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
:
AdGroupOperation
=
client
.
get_type
(
"AdGroupOperation"
)
ad_group_op2
.
create
.
name
=
f
"Broken AdGroup:
{
uuid
.
uuid4
()
}
"
ad_group_op2
.
create
.
campaign
=
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
:
AdGroupOperation
=
client
.
get_type
(
"AdGroupOperation"
)
ad_group_op3
.
create
.
name
=
ad_group_op1
.
create
.
name
ad_group_op3
.
create
.
campaign
=
resource_name
ad_group_operations
.
append
(
ad_group_op3
)
# Issue a mutate request, setting partial_failure=True.
request
:
MutateAdGroupsRequest
=
client
.
get_type
(
"MutateAdGroupsRequest"
)
request
.
customer_id
=
customer_id
request
.
operations
=
ad_group_operations
request
.
partial_failure
=
True
return
ad_group_service
.
mutate_ad_groups
(
request
=
request
)
def
is_partial_failure_error_present
(
response
:
MutateAdGroupsResponse
)
-
> bool
:
"""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
:
Any
=
getattr
(
response
,
"partial_failure_error"
,
None
)
code
:
int
=
int
(
getattr
(
partial_failure
,
"code"
,
0
))
# Default to 0 if None
return
code
!=
0
def
print_results
(
client
:
GoogleAdsClient
,
response
:
MutateAdGroupsResponse
)
-
> None
:
"""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
:
Any
=
getattr
(
response
,
"partial_failure_error"
,
None
)
# partial_failure_error.details is a repeated field and iterable
error_details
:
List
[
Any
]
=
getattr
(
partial_failure
,
"details"
,
[])
for
error_detail
in
error_details
:
# Retrieve an instance of the GoogleAdsFailure class from the client
failure_message
:
Any
=
client
.
get_type
(
"GoogleAdsFailure"
)
# Parse the string into a GoogleAdsFailure message instance.
# To access class-only methods on the message we retrieve its type.
GoogleAdsFailure
:
Any
=
type
(
failure_message
)
failure_object
:
Any
=
GoogleAdsFailure
.
deserialize
(
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 "
f
"
{
error
.
location
.
field_path_elements
[
0
]
.
index
}
occurred "
f
"
\n
Error message:
{
error
.
message
}
\n
Error code: "
f
"
{
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
:
if
not
message
:
continue
print
(
f
"Created ad group with resource_name:
{
message
.
resource_name
}
."
)
if
__name__
==
"__main__"
:
parser
=
argparse
.
ArgumentParser
(
description
=
"Adds an ad group for specified customer and campaign id."
)
# The following argument(s) should be provided to run the example.
parser
.
add_argument
(
"-c"
,
"--customer_id"
,
type
=
str
,
required
=
True
,
help
=
"The Google Ads customer ID."
,
)
parser
.
add_argument
(
"-i"
,
"--campaign_id"
,
type
=
str
,
required
=
True
,
help
=
"The campaign ID."
)
args
=
parser
.
parse_args
()
# GoogleAdsClient will read the google-ads.yaml configuration file in the
# home directory if none is specified.
googleads_client
:
GoogleAdsClient
=
GoogleAdsClient
.
load_from_storage
(
version
=
"v21"
)
main
(
googleads_client
,
args
.
customer_id
,
args
.
campaign_id
)
Ruby
# Encoding: utf-8
#
# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This code example shows how to deal with partial failures
require
'optparse'
require
'google/ads/google_ads'
require
'date'
def
add_ad_groups
(
customer_id
,
campaign_id
)
# GoogleAdsClient will read a config file from
# ENV['HOME']/google_ads_config.rb when called without parameters
client
=
Google
::
Ads
::
GoogleAds
::
GoogleAdsClient
.
new
ad_groups
=
[]
# This ad group should be created successfully.
ad_groups
<<
client
.
resource
.
ad_group
do
|
ag
|
ag
.
campaign
=
client
.
path
.
campaign
(
customer_id
,
campaign_id
)
ag
.
name
=
"Valid ad group:
#{
(
Time
.
new
.
to_f
*
1000
)
.
to_i
}
"
end
# This ad group should fail to create because it references an invalid campaign.
ad_groups
<<
client
.
resource
.
ad_group
do
|
ag
|
ag
.
campaign
=
client
.
path
.
campaign
(
customer_id
,
0
)
ag
.
name
=
"Invalid ad group:
#{
(
Time
.
new
.
to_f
*
1000
)
.
to_i
}
"
end
# This ad group should fail to create because it duplicates the name from the first one.
ad_groups
<<
client
.
resource
.
ad_group
do
|
ag
|
ag
.
campaign
=
client
.
path
.
campaign
(
customer_id
,
campaign_id
)
ag
.
name
=
ad_groups
.
first
.
name
end
operations
=
ad_groups
.
map
do
|
ag
|
client
.
operation
.
create_resource
.
ad_group
(
ag
)
end
response
=
client
.
service
.
ad_group
.
mutate_ad_groups
(
customer_id
:
customer_id
,
operations
:
operations
,
partial_failure
:
true
,
)
response
.
results
.
each_with_index
do
|
ad_group
,
i
|
if
ad_group
.
resource_name
!=
""
puts
(
"operations[
#{
i
}
] succeeded: Created ad group with id
#{
ad_group
.
resource_name
}
"
)
end
end
failures
=
client
.
decode_partial_failure_error
(
response
.
partial_failure_error
)
failures
.
each
do
|
failure
|
failure
.
errors
.
each
do
|
error
|
human_readable_error_path
=
error
.
location
.
field_path_elements
.
map
{
|
location_info
|
if
location_info
.
index
"
#{
location_info
.
field_name
}
[
#{
location_info
.
index
}
]"
else
"
#{
location_info
.
field_name
}
"
end
}
.
join
(
" > "
)
errmsg
=
"error occured creating ad group
#{
human_readable_error_path
}
"
\
" with value:
#{
error
.
trigger
.
string_value
}
"
\
" because
#{
error
.
message
.
downcase
}
"
puts
errmsg
end
end
end
if
__FILE__
==
$PROGRAM_NAME
options
=
{}
# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
options
[
:customer_id
]
=
'INSERT_CUSTOMER_ID_HERE'
options
[
:campaign_id
]
=
'INSERT_CAMPAIGN_ID_HERE'
OptionParser
.
new
do
|
opts
|
opts
.
banner
=
sprintf
(
'Usage: ruby %s [options]'
,
File
.
basename
(
__FILE__
))
opts
.
separator
''
opts
.
separator
'Options:'
opts
.
on
(
'-C'
,
'--customer-id CUSTOMER-ID'
,
String
,
'Customer ID'
)
do
|
v
|
options
[
:customer_id
]
=
v
end
opts
.
on
(
'-c'
,
'--campaign-id CAMPAIGN-ID'
,
String
,
'Ad Group ID'
)
do
|
v
|
options
[
:campaign_id
]
=
v
end
opts
.
separator
''
opts
.
separator
'Help:'
opts
.
on_tail
(
'-h'
,
'--help'
,
'Show this message'
)
do
puts
opts
exit
end
end
.
parse!
begin
add_ad_groups
(
options
.
fetch
(
:customer_id
)
.
tr
(
"-"
,
""
),
options
.
fetch
(
:campaign_id
),
)
rescue
Google
::
Ads
::
GoogleAds
::
Errors
::
GoogleAdsError
=
>
e
e
.
failure
.
errors
.
each
do
|
error
|
STDERR
.
printf
(
"Error with message: %s
\n
"
,
error
.
message
)
if
error
.
location
error
.
location
.
field_path_elements
.
each
do
|
field_path_element
|
STDERR
.
printf
(
"
\t
On field: %s
\n
"
,
field_path_element
.
field_name
)
end
end
error
.
error_code
.
to_h
.
each
do
|
k
,
v
|
next
if
v
==
:UNSPECIFIED
STDERR
.
printf
(
"
\t
Type: %s
\n\t
Code: %s
\n
"
,
k
,
v
)
end
end
raise
end
end
Perl
#!/usr/bin/perl -w
#
# Copyright 2019, Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example shows how to deal with partial failures. There are several ways
# of detecting partial failures. This example highlights the top main detection
# options: empty results and error instances.
use
strict
;
use
warnings
;
use
utf8
;
use
FindBin
qw($Bin)
;
use
lib
"$Bin/../../lib"
;
use
Google::Ads::GoogleAds::Client
;
use
Google::Ads::GoogleAds::Utils::GoogleAdsHelper
;
use
Google::Ads::GoogleAds::Utils::PartialFailureUtils
;
use
Google::Ads::GoogleAds::V21::Resources::AdGroup
;
use
Google::Ads::GoogleAds::V21::Services::AdGroupService::AdGroupOperation
;
use
Google::Ads::GoogleAds::V21::Utils::ResourceNames
;
use
Getopt::Long
qw(:config auto_help)
;
use
Pod::Usage
;
use
Cwd
qw(abs_path)
;
use
Data::Uniqid
qw(uniqid)
;
# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
my
$customer_id
=
"INSERT_CUSTOMER_ID_HERE"
;
my
$campaign_id
=
"INSERT_CAMPAIGN_ID_HERE"
;
sub
handle_partial_failure
{
my
(
$api_client
,
$customer_id
,
$campaign_id
)
=
@_
;
my
$ad_groups_response
=
create_ad_groups
(
$api_client
,
$customer_id
,
$campaign_id
);
check_if_partial_failure_error_exists
(
$ad_groups_response
);
print_results
(
$ad_groups_response
);
return
1
;
}
# Creates ad groups by enabling partial failure mode.
sub
create_ad_groups
{
my
(
$api_client
,
$customer_id
,
$campaign_id
)
=
@_
;
my
$campaign_resource_name
=
Google::Ads::GoogleAds::V21::Utils::ResourceNames::
campaign
(
$customer_id
,
$campaign_id
);
# This ad group should be created successfully - assuming the campaign in the
# params exists.
my
$ad_group1
=
Google::Ads::GoogleAds::V21::Resources::
AdGroup
-
> new
({
name
=
>
"Valid AdGroup: "
.
uniqid
(),
campaign
=
>
$campaign_resource_name
});
# This ad group will always fail - campaign ID 0 in the resource name is never
# valid.
my
$ad_group2
=
Google::Ads::GoogleAds::V21::Resources::
AdGroup
-
> new
({
name
=
>
"Broken AdGroup: "
.
uniqid
(),
campaign
=
>
Google::Ads::GoogleAds::V21::Utils::ResourceNames::
campaign
(
$customer_id
,
0
)});
# This ad group will always fail - duplicate ad group names are not allowed.
my
$ad_group3
=
Google::Ads::GoogleAds::V21::Resources::
AdGroup
-
> new
({
name
=
>
$ad_group1
-
> {
name
},
campaign
=
>
$campaign_resource_name
});
# Create ad group operations.
my
$ad_group_operation1
=
Google::Ads::GoogleAds::V21::Services::AdGroupService::
AdGroupOperation
-
>
new
({
create
=
>
$ad_group1
});
my
$ad_group_operation2
=
Google::Ads::GoogleAds::V21::Services::AdGroupService::
AdGroupOperation
-
>
new
({
create
=
>
$ad_group2
});
my
$ad_group_operation3
=
Google::Ads::GoogleAds::V21::Services::AdGroupService::
AdGroupOperation
-
>
new
({
create
=
>
$ad_group3
});
# Issue the mutate request, enabling partial failure mode.
my
$ad_groups_response
=
$api_client
-
> AdGroupService
()
-
> mutate
({
customerId
=
>
$customer_id
,
operations
=
>
[
$ad_group_operation1
,
$ad_group_operation2
,
$ad_group_operation3
],
partialFailure
=
>
"true"
});
return
$ad_groups_response
;
}
# Checks if partial failure error exists in the given mutate ad group response.
sub
check_if_partial_failure_error_exists
{
my
$ad_groups_response
=
shift
;
if
(
$ad_groups_response
-
> {
partialFailureError
})
{
print
"Partial failures occurred. Details will be shown below.\n"
;
}
else
{
print
"All operations completed successfully. No partial failures to show.\n"
;
}
}
# Prints results of the given mutate ad group response. For those that are partial
# failure, prints all their errors with corresponding operation indices. For those
# that succeeded, prints the resource names of created ad groups.
sub
print_results
{
my
$ad_groups_response
=
shift
;
# Find the failed operations by looping through the results.
while
(
my
(
$operation_index
,
$result
)
=
each
@
{
$ad_groups_response
-
> {
results
}})
{
if
(
is_partial_failure_result
(
$result
))
{
my
$google_ads_errors
=
get_google_ads_errors
(
$operation_index
,
$ad_groups_response
-
> {
partialFailureError
});
foreach
my
$google_ads_error
(
@$google_ads_errors
)
{
printf
"Operation %d failed with error: %s\n"
,
$operation_index
,
$google_ads_error
-
> {
message
};
}
}
else
{
printf
"Operation %d succeeded: ad group with resource name '%s'.\n"
,
$operation_index
,
$result
-
> {
resourceName
};
}
}
}
# Don't run the example if the file is being included.
if
(
abs_path
(
$0
)
ne
abs_path
(
__FILE__
))
{
return
1
;
}
# Get Google Ads Client, credentials will be read from ~/googleads.properties.
my
$api_client
=
Google::Ads::GoogleAds::
Client
-
> new
();
# By default examples are set to die on any server returned fault.
$api_client
-
> set_die_on_faults
(
1
);
# Parameters passed on the command line will override any parameters set in code.
GetOptions
(
"customer_id=s"
=
>
\
$customer_id
,
"campaign_id=i"
=
>
\
$campaign_id
);
# Print the help message if the parameters are not initialized in the code nor
# in the command line.
pod2usage
(
2
)
if
not
check_params
(
$customer_id
,
$campaign_id
);
# Call the example.
handle_partial_failure
(
$api_client
,
$customer_id
=~
s/-//g
r
,
$campaign_id
);
=pod
=head1 NAME
handle_partial_failure
=head1 DESCRIPTION
This example shows how to deal with partial failures. There are several ways of
detecting partial failures. This example highlights the top main detection
options: empty results and error instances.
=head1 SYNOPSIS
handle_partial_failure.pl [options]
-help Show the help message.
-customer_id The Google Ads customer ID.
-campaign_id The campaign ID.
=cut
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License
, and code samples are licensed under the Apache 2.0 License
. For details, see the Google Developers Site Policies
. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-09-03 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-03 UTC."],[[["\u003cp\u003eThe code examples demonstrate handling partial failures in Google Ads API requests, ensuring successful operations complete even if some fail.\u003c/p\u003e\n"],["\u003cp\u003ePartial failures occur when some operations within a batch request succeed while others encounter errors.\u003c/p\u003e\n"],["\u003cp\u003eThe examples cover Java, C#, PHP, Python, Ruby, and Perl, illustrating language-specific error handling techniques.\u003c/p\u003e\n"],["\u003cp\u003eDetailed error information, including messages, codes, and locations, is extracted and displayed for failed operations.\u003c/p\u003e\n"],["\u003cp\u003eSetting the \u003ccode\u003epartial_failure\u003c/code\u003e flag to \u003ccode\u003etrue\u003c/code\u003e enables the API to process all operations and report individual successes and failures.\u003c/p\u003e\n"]]],[],null,[]]