Skip to main content
Send feedback
Partial Failure Stay organized with collections
Save and categorize content based on your preferences.
In the Google Ads API, you can request that valid operations be committed and failed
ones return errors. This feature—called partial failure—lets you
handle the failed operations separately at the end. It is available in
non-get methods of many Google Ads API services.
Key Point: Not all services support the partial failure mode. If a given method
accepts a request that has the partial_failure
field, it means that the
method supports this mode. For example, the MutateAdGroups
method of AdGroupService
accepts MutateAdGroupsRequest
, which contains partial_failure
, meaning that MutateAdGroups
method supports partial failure.
Technical details
To utilize this feature, set the partialFailure
parameter of the method you'd
like to use. This can be a bit different in each client library. For example, 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
)
PHP
mutateAdGroups($customerId, $operations, ['partialFailure' => true])
Python
mutate_ad_groups
(
customer_id
,
operations
,
partial_failure
=
True
)
Ruby
mutate_ad_groups
(
customer_id
,
operations
,
partial_failure
:
true
)
Perl
mutate
({
customerId
=>
$customer_id
,
operations
=>
$operations
,
partialFailure
=>
'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
Suppose you need to add a set of ad groups to your account, but 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
(
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
());
}
}
C#
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
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)
);
}
Python
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
)
Ruby
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
.
rb
Perl
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
;
}
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
;
}
PHP
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
);
}
}
Python
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
Ruby
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
.
rb
Perl
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"
;
}
}
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. Each submitted operation can return at most one GoogleAdsFailure
object, and each GoogleAdsFailure
contains one or more GoogleAdsError
errors.
GoogleAdsError
tells you the error 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
)
{
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#
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
++
;
}
}
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++;
}
}
Python
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
}
."
)
Ruby
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
.
rb
Perl
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
};
}
}
}
Code examples
The ErrorHandling
folder of each client library
contains the following code example that shows how to use this feature:
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
Send feedback
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.
Need to tell us more?
[[["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 Google Ads API now supports partial failure, allowing successful operations to be committed even if some operations within the same request fail.\u003c/p\u003e\n"],["\u003cp\u003ePartial failure is activated by setting the \u003ccode\u003epartialFailure\u003c/code\u003e parameter and is supported in various client libraries (Java, C#, PHP, Python, Ruby, Perl).\u003c/p\u003e\n"],["\u003cp\u003eWhen partial failure is enabled, the API response includes details about both successful and failed operations, allowing developers to handle errors gracefully.\u003c/p\u003e\n"],["\u003cp\u003eDevelopers can access specific error details for failed operations through the \u003ccode\u003epartial_failure_error\u003c/code\u003e field in the response and use client library utilities for simplified error handling.\u003c/p\u003e\n"],["\u003cp\u003eThis feature enhances the robustness of Google Ads API interactions by ensuring that valid operations are processed while providing detailed feedback on any failures.\u003c/p\u003e\n"]]],[],null,[]]