Learn about troubleshooting steps that you might find helpful if you run into problems using Pub/Sub.

Cannot create a subscription

Check that you have done the following:

  • Specified a subscription name in the name field. For version v1beta2 and above, the subscription name must be in the form projects/project-identifier/subscriptions/subscription-name.
  • Specified the name of an existing topic to which you want to subscribe, in the topic field. For version v1beta2 and above, the topic name must be in the form projects/project-identifier/topics/topic-name.
  • Specified https:// in lower case (not http:// or HTTPS://) as the protocol for your receiving URL in the pushEndpoint field.

Push subscriber not receiving any messages

Check the following:

  • Look in Stackdriver Monitoring for errors related to the subscription in question.
  • On App Engine, we recommend that you use the /_ah/push-handlers/ prefix in the endpoints URL path, as described in Registering App Engine endpoints. This code allows the endpoint to receive push messages from Pub/Sub API.
  • In other environments, make sure that your endpoint URL can be accessed from the Internet without requiring sign-in. You can check that the URL is not restricted by accessing it with a diagnostic tool such as cURL.
  • For domains other than, make sure to register the domain in the Google Cloud Console. See Registering other endpoints for details.

Push messages delivery is late by hours

One unacknowledged push message can delay the delivery of new ones. A message is unacknowledged if the push endpoint fails or returns a status code other than 200, 201, 202, 204, or 102. To get rid of the delay, update the endpoint code to handle the failed messages or manually pull and then acknowledge them. See the Monitoring overview for more information about detecting unacknowledged messages and creating alerts.

403 (Forbidden) error

If you get this error, do the following:

  • Make sure you've enabled the Pub/Sub API in the Cloud Console.
  • Make sure that the principal making the request has the required permissions on the relevant Pub/Sub API resources, especially if you are using Pub/Sub API for cross-project communication.
  • If you're using Dataflow, make sure that both <projectId> and the Compute Engine Service account <projectId> have the required permissions on the relevant Pub/Sub API resource. See Dataflow Security and Permissions for more information.
  • If you're using App Engine, check your project's Permissions page to see if an App Engine Service Account is listed as an Editor. If it is not, add your App Engine Service Account as an Editor. Normally, the App Engine Service Account is of the form <project-id>

Dealing with duplicates and forcing retries

When you do not acknowledge a message before its acknowledgement deadline has expired, Pub/Sub resends the message. As a result, Pub/Sub can send duplicate messages. Use Stackdriver to monitor acknowledge operations with the expired response code to detect this condition. To get this data, select the Acknowledge message operations metric, then group or filter it by the response_code label. Note that response_code is a system label on a metric—it is not a metric.

Use Stackdriver to to search for expired message acknowledgement deadlines

To reduce the duplication rate, extend the message deadline.

  • Client libraries handle deadline extension automatically, but you should note that there are default limits on the maximum extension deadline that can be configured.
  • If you are building your own client library, use the modifyAckDeadline method to extend the acknowledgement deadline.

Alternately, to force Pub/Sub to retry a message, set modifyAckDeadline to 0.

Using excessive administrative operations

If you find that you're using up too much of your quota for administrative operations, you might need to refactor your code. As an illustration, consider this pseudo-code. In this example, an administrative operation (GET) is being used to check for the presence of a subscription before it attempts to consume its resources. Both GET and CREATE are admin operations:

    if !GetSubscription my-sub {
     CreateSubscription my-sub
    Consume from subscription my-sub

A more efficient pattern is to try to consume messages from the subscription (assuming that you can be reasonably sure of the subscription's name). In this optimistic approach, you only get or create the subscription if there is an error. Consider this example:

    try {
      Consume from subscription my-sub
    } catch NotFoundError {
      CreateSubscription my-sub
      Consume from subscription my-sub